forked from orion/obsidian
update
This commit is contained in:
parent
d74fc46755
commit
3ee2a9bbbd
50
fp/.obsidian/workspace.json
vendored
50
fp/.obsidian/workspace.json
vendored
@ -11,8 +11,12 @@
|
|||||||
"id": "6465d16034124b8f",
|
"id": "6465d16034124b8f",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "graph",
|
"type": "markdown",
|
||||||
"state": {}
|
"state": {
|
||||||
|
"file": "Language/Functions/Defining/Guard Clause.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -81,6 +85,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "backlink",
|
"type": "backlink",
|
||||||
"state": {
|
"state": {
|
||||||
|
"file": "Language/Functions/Defining/Guard Clause.md",
|
||||||
"collapseAll": false,
|
"collapseAll": false,
|
||||||
"extraContext": false,
|
"extraContext": false,
|
||||||
"sortOrder": "alphabetical",
|
"sortOrder": "alphabetical",
|
||||||
@ -97,6 +102,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "outgoing-link",
|
"type": "outgoing-link",
|
||||||
"state": {
|
"state": {
|
||||||
|
"file": "Language/Functions/Defining/Guard Clause.md",
|
||||||
"linksCollapsed": false,
|
"linksCollapsed": false,
|
||||||
"unlinkedCollapsed": true
|
"unlinkedCollapsed": true
|
||||||
}
|
}
|
||||||
@ -118,7 +124,9 @@
|
|||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "outline",
|
"type": "outline",
|
||||||
"state": {}
|
"state": {
|
||||||
|
"file": "Language/Functions/Defining/Guard Clause.md"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -142,6 +150,24 @@
|
|||||||
},
|
},
|
||||||
"active": "6465d16034124b8f",
|
"active": "6465d16034124b8f",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
|
"Language/Functions/Defining/Pattern Matching.md",
|
||||||
|
"Language/Functions/Applying.md",
|
||||||
|
"Language/Functions/Composition.md",
|
||||||
|
"Language/Functions/Currying.md",
|
||||||
|
"Language/Functions.md",
|
||||||
|
"Terminology/Point-free.md",
|
||||||
|
"Language/Infix Operators/Common Operators/Applying & Composing Functions.md",
|
||||||
|
"Language/Functions/Defining.md",
|
||||||
|
"Language/Expressions/case .. of.md",
|
||||||
|
"Language/Expressions/Lambda Functions.md",
|
||||||
|
"Language/Functions/Defining/Guard Clause.md",
|
||||||
|
"Language/Expressions/let .. in ...md",
|
||||||
|
"Language/Expressions/if .. then .. else ...md",
|
||||||
|
"Language/Expressions/do notation.md",
|
||||||
|
"Classes/Functor/Apply.md",
|
||||||
|
"Classes/Functor/Applicative.md",
|
||||||
|
"Classes/Bind/Monad.md",
|
||||||
|
"Classes/Bind/Bind.md",
|
||||||
"Classes/Alternative/Alt.md",
|
"Classes/Alternative/Alt.md",
|
||||||
"Classes/Alternative/Plus.md",
|
"Classes/Alternative/Plus.md",
|
||||||
"Monads/Transformers/MaybeT.md",
|
"Monads/Transformers/MaybeT.md",
|
||||||
@ -151,31 +177,13 @@
|
|||||||
"Monads/Transformers/StateT.md",
|
"Monads/Transformers/StateT.md",
|
||||||
"Monads/Transformers",
|
"Monads/Transformers",
|
||||||
"Classes/Alternative/Alternative.md",
|
"Classes/Alternative/Alternative.md",
|
||||||
"Classes/Functor/Applicative.md",
|
|
||||||
"Classes/Functor/Apply.md",
|
|
||||||
"Classes/Functor/Functor.md",
|
|
||||||
"Classes/Collapsing",
|
"Classes/Collapsing",
|
||||||
"Classes/Bind",
|
"Classes/Bind",
|
||||||
"Classes/Functor",
|
"Classes/Functor",
|
||||||
"Classes/Alternative",
|
"Classes/Alternative",
|
||||||
"Language/Infix Operators/Common Operators/Data.md",
|
|
||||||
"Classes/Traversable.md",
|
|
||||||
"Data/Collections/NonEmptyArray.md",
|
|
||||||
"Data/Collections/NonEmptyList.md",
|
|
||||||
"Data/String.md",
|
|
||||||
"Data/Collections.md",
|
|
||||||
"Data/Collections/HashMap.md",
|
|
||||||
"Data/Product",
|
"Data/Product",
|
||||||
"Data/Sum",
|
"Data/Sum",
|
||||||
"Data/Collections/HashSet.md",
|
|
||||||
"Data/Collections/Set.md",
|
|
||||||
"Data/Collections/List.md",
|
|
||||||
"Data/Collections/Map.md",
|
|
||||||
"Data/Collections",
|
"Data/Collections",
|
||||||
"Language/Row Types.md",
|
|
||||||
"Language/Row Types/Variant.md",
|
|
||||||
"Language/Row Types/Record.md",
|
|
||||||
"Data/Product/Tuple.md",
|
|
||||||
"Language/Row Types",
|
"Language/Row Types",
|
||||||
"Classes/Math",
|
"Classes/Math",
|
||||||
"Untitled 1.canvas",
|
"Untitled 1.canvas",
|
||||||
|
23
fp/Language/Expressions/Lambda Functions.md
Normal file
23
fp/Language/Expressions/Lambda Functions.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
lambda functions are anonymous functions (as opposed to [[Functions|top-level functions]]) that can be written anywhere:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
\ <params> -> <body>
|
||||||
|
```
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
prependHello a = "hello, " <> a
|
||||||
|
|
||||||
|
appendName = \a -> a <> "henry!"
|
||||||
|
|
||||||
|
str = appendName $ prependHello ""
|
||||||
|
-- hello, henry!
|
||||||
|
```
|
||||||
|
|
||||||
|
their parameters can destructure their arguments:
|
||||||
|
```haskell
|
||||||
|
let
|
||||||
|
getFoo = \{foo} -> foo
|
||||||
|
in
|
||||||
|
getFoo {foo: "hello"}
|
||||||
|
-- "hello"
|
||||||
|
```
|
@ -1,4 +1,4 @@
|
|||||||
Pattern matching
|
Structural pattern matching expression
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
case <expr> of
|
case <expr> of
|
||||||
@ -18,7 +18,7 @@ where `arm` is:
|
|||||||
- array literals, containing patterns
|
- array literals, containing patterns
|
||||||
- wildcard `_`
|
- wildcard `_`
|
||||||
|
|
||||||
### Guard Clauses
|
## Guard Clauses
|
||||||
Case arms can have [[Functions/Defining/Guard Clause|guard clauses]] like [[Functions|function]] definitions:
|
Case arms can have [[Functions/Defining/Guard Clause|guard clauses]] like [[Functions|function]] definitions:
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
@ -28,7 +28,22 @@ case _ of
|
|||||||
| otherwise -> Nothing
|
| otherwise -> Nothing
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
## Anonymous expression
|
||||||
|
Underscore can be placed in the expression position to write an [[Lambda Functions|anonymous function]] that immediately case matches on its argument:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
case _ of
|
||||||
|
Foo -> true
|
||||||
|
Bar -> false
|
||||||
|
|
||||||
|
-- equivalent to
|
||||||
|
|
||||||
|
\a -> case a of
|
||||||
|
Foo -> true
|
||||||
|
Bar -> false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
Match on `Int` when zero
|
Match on `Int` when zero
|
||||||
```haskell
|
```haskell
|
||||||
|
@ -0,0 +1,209 @@
|
|||||||
|
Do notation is sugar for [[Bind|bind]] `>>=`, allowing imperative blocks that use bind as the driver of the "and-then" behavior for the specific type being returned.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
main :: Effect Unit
|
||||||
|
main = do
|
||||||
|
log "hello, world!"
|
||||||
|
log "foo bar baz"
|
||||||
|
|
||||||
|
-- logs:
|
||||||
|
-- hello, world!
|
||||||
|
-- foo bar baz
|
||||||
|
```
|
||||||
|
|
||||||
|
Do blocks are opened with the `do` keyword and support only a few operations:
|
||||||
|
|
||||||
|
- [[#bind|"await" with <-]]
|
||||||
|
- [[#let-bindings|define local variables]]
|
||||||
|
- [[#eval and ignore|evaluate an expression but discard its output]]
|
||||||
|
- [[#return|return an expression]]
|
||||||
|
|
||||||
|
statements in do blocks are evaluated line-by-line top-to-bottom, just like any other imperative language.
|
||||||
|
|
||||||
|
## bind
|
||||||
|
The left-arrow `<-` in `do` blocks is analogous to the `await` keyword in JS, C# & Java, and the question mark operator in Rust.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
intPositive :: Int -> Maybe Int
|
||||||
|
intPositive n
|
||||||
|
| n > 0 = Just n
|
||||||
|
| otherwise = Nothing
|
||||||
|
|
||||||
|
f :: String -> Maybe Int
|
||||||
|
f s = do
|
||||||
|
-- if `s` can't be parsed, returns Nothing early
|
||||||
|
num <- Int.fromString s
|
||||||
|
-- if `num` is <= 0, returns Nothing early
|
||||||
|
pos <- intPositive num
|
||||||
|
Just pos
|
||||||
|
```
|
||||||
|
|
||||||
|
This desugars to:
|
||||||
|
```haskell
|
||||||
|
f s =
|
||||||
|
Int.fromString s
|
||||||
|
>>= ( \num ->
|
||||||
|
intPositive num
|
||||||
|
>>= (\pos -> Just pos)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## let-bindings
|
||||||
|
Related to [[let .. in ..]], You can define new local variables in the middle of do blocks that can depend on previous bindings:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
do
|
||||||
|
a <- Just 1
|
||||||
|
let
|
||||||
|
b = a + 1
|
||||||
|
c = b + 1
|
||||||
|
Just c
|
||||||
|
-- evaluates to (Just 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!attention]- Unexpected or mismatched indentation
|
||||||
|
> A common gotcha with let-bindings in do blocks is only indenting once after trying to insert a line break after the equals:
|
||||||
|
> ```haskell
|
||||||
|
> do
|
||||||
|
> a <- Just 1
|
||||||
|
> let b =
|
||||||
|
> a + 1
|
||||||
|
> Just b
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```text
|
||||||
|
> [ERROR 1/1 ErrorParsingModule] ...
|
||||||
|
>
|
||||||
|
> 4 a + 1
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> Unable to parse module:
|
||||||
|
> Unexpected or mismatched indentation
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> This happens because oneline let bindings
|
||||||
|
> ```haskell
|
||||||
|
> do
|
||||||
|
> let a = b
|
||||||
|
> ..
|
||||||
|
> ```
|
||||||
|
> are identical to
|
||||||
|
> ```haskell
|
||||||
|
> do
|
||||||
|
> let
|
||||||
|
> a = b
|
||||||
|
> ..
|
||||||
|
> ```
|
||||||
|
> So when you break after the equals and only indent once:
|
||||||
|
> ```haskell
|
||||||
|
> do
|
||||||
|
> let a =
|
||||||
|
> b
|
||||||
|
> ..
|
||||||
|
> ```
|
||||||
|
> what you're actually writing is
|
||||||
|
> ```haskell
|
||||||
|
> do
|
||||||
|
> let
|
||||||
|
> a =
|
||||||
|
> b
|
||||||
|
> ..
|
||||||
|
> ```
|
||||||
|
|
||||||
|
## eval and ignore
|
||||||
|
When an expression returns `m Unit`, you don't have to write an arrow:
|
||||||
|
```haskell
|
||||||
|
guard :: Boolean -> Maybe Unit
|
||||||
|
guard true = Just unit
|
||||||
|
guard false = Nothing
|
||||||
|
|
||||||
|
do
|
||||||
|
n <- Int.fromString "123"
|
||||||
|
-- when `n > 0`, this resolves to `Just unit` and
|
||||||
|
-- the execution continues.
|
||||||
|
-- If this is Nothing, the block short-circuits
|
||||||
|
-- and returns Nothing.
|
||||||
|
guard (n > 0)
|
||||||
|
Just n
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to discard a value other than unit, you need to use the discard syntax `_ <- x`
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
main :: Effect Unit
|
||||||
|
main = do
|
||||||
|
fooTxt <- File.createWriteStream "foo.txt"
|
||||||
|
-- Stream.writeString returns a Boolean
|
||||||
|
-- indicating whether the stream needs us
|
||||||
|
-- to wait for the `drain` event before writing
|
||||||
|
-- more, but we don't care here.
|
||||||
|
_ <- Stream.writeString UTF8 "foo" fooTxt
|
||||||
|
pure unit
|
||||||
|
```
|
||||||
|
|
||||||
|
## return
|
||||||
|
the last statement in a do block is the expression the do block will return, and can't be a let-binding or bind statement:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
-- block immediately resolves with `Just ""`
|
||||||
|
do
|
||||||
|
Just ""
|
||||||
|
```
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
-- block resolves with `Just foo`
|
||||||
|
do
|
||||||
|
foo <- getFoo
|
||||||
|
Just foo
|
||||||
|
```
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
-- block resolves with `Just "foo"`
|
||||||
|
do
|
||||||
|
do
|
||||||
|
do
|
||||||
|
do
|
||||||
|
Just "foo"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
`do` in [[Maybe]] allows us to return early with empty values.
|
||||||
|
|
||||||
|
In this example, `getApiUrlPort` will return Nothing if:
|
||||||
|
- environment variable `API_URL` is unset
|
||||||
|
- `API_URL` is not a valid URL
|
||||||
|
- `API_URL` is a valid URL, but the port isn't set
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
lookupEnv :: String -> Maybe String
|
||||||
|
urlFromString :: String -> Maybe URL
|
||||||
|
urlPort :: URL -> Maybe Int
|
||||||
|
|
||||||
|
getApiUrlPort = do
|
||||||
|
apiUrlString <- lookupEnv "API_URL"
|
||||||
|
apiUrl <- urlFromString apiUrlString
|
||||||
|
urlPort apiUrl
|
||||||
|
```
|
||||||
|
|
||||||
|
`do` in [[Either]] allows us to return early with errors.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
lookupEnv :: String -> Either String String
|
||||||
|
urlFromString :: String -> Either String URL
|
||||||
|
urlPort :: URL -> Maybe Int
|
||||||
|
|
||||||
|
getApiUrlPort = do
|
||||||
|
apiUrlString <- lookupEnv "API_URL"
|
||||||
|
apiUrl <- urlFromString apiUrlString
|
||||||
|
liftMaybe ("no port set in URL " <> apiUrlString)
|
||||||
|
$ urlPort apiUrl
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]- `liftMaybe`
|
||||||
|
> liftMaybe allows us to turn `Maybe a` into any `m a` as long as `m` supports [[MonadThrow|throwing]] errors.
|
||||||
|
>
|
||||||
|
> In the above example, if `urlPort` is `Nothing`, it will return `Left "no port set in ..."`.
|
||||||
|
>
|
||||||
|
> ```haskell
|
||||||
|
> liftMaybe :: forall m e a. MonadThrow e m => e -> Maybe a => m a
|
||||||
|
> ```
|
@ -0,0 +1,5 @@
|
|||||||
|
Conditional expression, similar to ternary expressions in imperative languages:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
if a == b then "foo" else "bar"
|
||||||
|
```
|
@ -0,0 +1,33 @@
|
|||||||
|
`let .. in ..` is an expression with some scoped variables, separated by newlines:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
let
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
in
|
||||||
|
a + b
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
> there is a second local let-binding syntax, `where`:
|
||||||
|
> ```haskell
|
||||||
|
> a + b
|
||||||
|
> where
|
||||||
|
> a = 1
|
||||||
|
> b = 2
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Recursive Fibonacci generator, using a helper function `go`
|
||||||
|
```haskell
|
||||||
|
fib n =
|
||||||
|
let
|
||||||
|
go ns a b =
|
||||||
|
if Array.length ns == n then
|
||||||
|
ns
|
||||||
|
else
|
||||||
|
go (ns <> [a]) b (a + b)
|
||||||
|
in
|
||||||
|
go [] 1 1
|
||||||
|
```
|
@ -1 +1,3 @@
|
|||||||
The backbone of functional programming. Functions can be constants, transform [[Data Structures|data]], perform [[Effect|effects]] and much more.
|
The backbone of functional programming. Functions can be constants, transform [[Data Structures|data]], perform [[Effect|effects]] and much more.
|
||||||
|
|
||||||
|
Functions can be [[Defining|defined]] as top-level [[Modules|module]] items, [[Lambda Functions|lambda functions]], [[Infix Operators|infix operators]] or created by [[Currying|partially applying]] functions.
|
@ -1,6 +1,6 @@
|
|||||||
[[Functions]] are curried in PureScript, meaning that "a function of 2 arguments" is actually "a function of 1 argument, returning a function of 1 argument."
|
[[Functions]] are curried in PureScript, meaning that "a function of 2 arguments" is actually "a function of 1 argument, returning a function of 1 argument."
|
||||||
|
|
||||||
This allows you to call many functions point-free, and think in terms of "building up to a conclusion" rather than "i need everything at once."
|
This allows you to call many functions [[Point-free|point-free]], and think in terms of "building up to a conclusion" rather than "i need everything at once."
|
||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ Walking through this:
|
|||||||
|
|
||||||
if we give `add` a single `Int` argument, it will return a function of type `Int -> Int`. This function is the "second half" of `add`, waiting for it's second argument. Since `Int -> Int` is the type of `add2`, we can simply say `add2 = add 2`.
|
if we give `add` a single `Int` argument, it will return a function of type `Int -> Int`. This function is the "second half" of `add`, waiting for it's second argument. Since `Int -> Int` is the type of `add2`, we can simply say `add2 = add 2`.
|
||||||
|
|
||||||
> [!info]
|
> [!tip]
|
||||||
> as a rule, any time a function's last argument is passed as the last argument to another function, you can remove both.
|
> as a rule, any time a function's last argument is passed as the last argument to another function, you can remove both.
|
||||||
> ```haskell
|
> ```haskell
|
||||||
> f a = g b c a
|
> f a = g b c a
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
Single [[Functions|Functions]] [[Defining/Pattern Matching|implementations]] may have 1 or more guard clauses.
|
Single [[Functions|Functions]] [[Defining/Pattern Matching|implementations]] may have 1 or more guard clauses.
|
||||||
|
|
||||||
> [!info]
|
> [!tip]
|
||||||
> [[case .. of]] expressions can also use guard clauses.
|
> [[case .. of]] expressions can also use guard clauses.
|
||||||
|
|
||||||
These allow functions to switch on boolean expressions based on the inputs, and can often take up less space than explicit [[Expressions/if .. then .. else ..]] expressions.
|
These allow functions to switch on boolean expressions based on the inputs, and can often take up less space than explicit [[if .. then .. else ..]] expressions.
|
||||||
|
|
||||||
Guard patterns are placed after the function arguments and take the form `| <Boolean expr> = <body>`. There can be any number of guard patterns, as long as all cases are exhaustively covered.
|
Guard patterns are placed after the function arguments and take the form `| <Boolean expr> = <body>`. There can be any number of guard patterns, as long as all cases are exhaustively covered.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
Strings can't be structurally pattern matched, so in order to ask if a string starts with a substring we need to call a function like `Data.String.Utils.startsWith`.
|
[[String]]s can't be structurally pattern matched aside from the entire string. In order to ask if a string starts with a substring we need to call a function like `Data.String.Utils.startsWith`.
|
||||||
|
|
||||||
We could do this with `if then else`:
|
We could do this with `if then else`:
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ ensureLeadingSlash str
|
|||||||
|
|
||||||
When the first pattern `String.Util.startsWith "/" str` returns `true`, the function will use `... = str`. Otherwise, it will prepend `/` to `str`.
|
When the first pattern `String.Util.startsWith "/" str` returns `true`, the function will use `... = str`. Otherwise, it will prepend `/` to `str`.
|
||||||
|
|
||||||
> [!tip]
|
> [!tip] `otherwise`
|
||||||
> `otherwise` is simply an alias for `true`, specifically for better-reading fallthrough guard patterns.
|
> `otherwise` is simply an alias for `true`, specifically for better-reading fallthrough guard patterns.
|
||||||
|
|
||||||
Much less often, but occasionally useful is the ability to structurally pattern match in a guard clause:
|
Much less often, but occasionally useful is the ability to structurally pattern match in a guard clause:
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
[[Functions]] may have multiple implementations that change behavior based on the shape of the arguments.
|
[[Functions]] may have multiple implementations that change behavior based on the shape of the arguments.
|
||||||
|
|
||||||
> [!note]
|
> [!tip]- [[case .. of]]
|
||||||
> You can always replace this with a [[case .. of|case expression]].
|
> Pattern matching in function definitions can always be rewritten as [[case .. of]].
|
||||||
|
> ```haskell
|
||||||
|
> isA "a" = true
|
||||||
|
> isA _ = false
|
||||||
|
> ```
|
||||||
|
> can be rewritten as
|
||||||
|
> ```haskell
|
||||||
|
> isA a = case a of
|
||||||
|
> "a" -> true
|
||||||
|
> _ -> false
|
||||||
|
> ```
|
||||||
|
|
||||||
This is _similar_ to method overloading in OOP languages, but differs in that the number of arguments and type of the arguments must be the same for all implementations.
|
This is _similar_ to method overloading in OOP languages, but differs in that the number of arguments and type of the arguments must be the same for all implementations.
|
||||||
|
|
||||||
|
18
fp/Terminology/Point-free.md
Normal file
18
fp/Terminology/Point-free.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Written without explicit arguments and application, e.g.
|
||||||
|
```haskell
|
||||||
|
foo a b = bar a b
|
||||||
|
```
|
||||||
|
can be written point-free as
|
||||||
|
```haskell
|
||||||
|
foo = bar
|
||||||
|
```
|
||||||
|
|
||||||
|
Rewriting
|
||||||
|
```haskell
|
||||||
|
\a -> g (f a)
|
||||||
|
```
|
||||||
|
as
|
||||||
|
```haskell
|
||||||
|
g << f
|
||||||
|
```
|
||||||
|
is also referred to as point-free.
|
Loading…
Reference in New Issue
Block a user