You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/chapter3.md
+25-24Lines changed: 25 additions & 24 deletions
Original file line number
Diff line number
Diff line change
@@ -481,13 +481,13 @@ In the case of `insertEntry`, _eta conversion_ has resulted in a very clear defi
481
481
482
482
## Property Accessors
483
483
484
-
One common pattern is to use a function to access an individual fields (or "properties") of a record. An inline function to extract an `Address` from an `Entry` could be written as:
484
+
One common pattern is to use a function to access individual fields (or "properties") of a record. An inline function to extract an `Address` from an `Entry` could be written as:
485
485
486
486
```haskell
487
487
\entry -> entry.address
488
488
```
489
489
490
-
PureScript provides an equivalent [_property accessor_](https://github.com/purescript/documentation/blob/master/language/Syntax.md#property-accessors) shorthand, where an underscore is followed by a field name, so the inline function above is equivalent to:
490
+
PureScript also allows [_property accessor_](https://github.com/purescript/documentation/blob/master/language/Syntax.md#property-accessors) shorthand, where an underscore acts as the anonymous fuction argument, so the inline function above is equivalent to:
491
491
492
492
```haskell
493
493
_.address
@@ -561,7 +561,7 @@ This type signature says that `findEntry` takes two strings, the first and last
561
561
And here is the definition of`findEntry`:
562
562
563
563
```haskell
564
-
findEntry firstName lastName book =head$filter filterEntry book
564
+
findEntry firstName lastName book =head(filter filterEntry book)
@@ -591,7 +591,7 @@ However, this chapter has also included examples of _infix_ [binary operators](h
591
591
infix4 eq as ==
592
592
```
593
593
594
-
and therefore `entry.firstName == firstName` in `filterEntry` could be replaced with the `eq entry.firstName firstName`.
594
+
and therefore `entry.firstName == firstName` in `filterEntry` could be replaced with the `eq entry.firstName firstName`. We'll cover a few more examples of defining infix operators later in this section.
595
595
596
596
There are situations where putting a prefix function in an infix position as an operator leads to more readable code. One example is the `mod` function:
597
597
@@ -621,7 +621,7 @@ book3 = insertEntry john (insertEntry peggy (insertEntry ned emptyBook))
621
621
book4 = john `insertEntry` (peggy `insertEntry` (ned `insertEntry` emptyBook))
622
622
```
623
623
624
-
We can also define an operator alias/synonym for `insertEntry.` We'll arbitrarily choose `++` for this operator, give it a [precedence](https://github.com/purescript/documentation/blob/master/language/Syntax.md#precedence) of `5`, and make it right [associative](https://github.com/purescript/documentation/blob/master/language/Syntax.md#associativity) using `infixr`:
624
+
We can also define an infix operator alias (or synonym) for `insertEntry.` We'll arbitrarily choose `++` for this operator, give it a [precedence](https://github.com/purescript/documentation/blob/master/language/Syntax.md#precedence) of `5`, and make it right [associative](https://github.com/purescript/documentation/blob/master/language/Syntax.md#associativity) using `infixr`:
625
625
626
626
```haskell
627
627
infixr5 insertEntry as ++
@@ -630,7 +630,7 @@ infixr 5 insertEntry as ++
630
630
This new operator lets us rewrite the above `book4` example as:
631
631
632
632
```haskell
633
-
book6= john ++ (peggy ++ (ned ++ emptyBook))
633
+
book5= john ++ (peggy ++ (ned ++ emptyBook))
634
634
```
635
635
636
636
and the right associativity of our new `++` operator lets us get rid of the parentheses without changing the meaning:
@@ -639,11 +639,16 @@ and the right associativity of our new `++` operator lets us get rid of the pare
639
639
book6 = john ++ peggy ++ ned ++ emptyBook
640
640
```
641
641
642
-
Likewise, in the code for `findEntry` above, we used a different form of function application: the `head` function was applied to the expression `filter filterEntry book` by using the infix `$` symbol.
642
+
Another common technique for eliminating parens is to use `apply`'s infix operator `$`, along with your standard prefix functions.
643
+
644
+
For example, the earlier `book3` example could be rewritten as:
645
+
```haskell
646
+
book7 = insertEntry john $ insertEntry peggy $ insertEntry ned emptyBook
647
+
```
643
648
644
-
This is equivalent to the usual application `head (filter filterEntry book)`
649
+
Substituting `$` for parens is usually easier to type and (arguably) easier to read. A mnemonic to remember the meaning of this symbol is to think of the dollar sign as being drawn from two parens that are also being crossed-out, suggesting the parens are now unnecessary.
645
650
646
-
`($)` is just an alias for a regular function called `apply`, which is defined in the Prelude. It is defined as follows:
651
+
Note that `$` isn't special syntax that's hardcoded into the language. It's simply the infix operator for a regular function called `apply`, which is defined in the Prelude as follows:
647
652
648
653
```haskell
649
654
apply::forallab. (a->b) ->a->b
@@ -652,23 +657,15 @@ apply f x = f x
652
657
infixr0 apply as $
653
658
```
654
659
655
-
So `apply` takes a function and a value and applies the function to the value. The `infixr` keyword is used to define `($)` as an alias for `apply`.
656
-
657
-
But why would we want to use `$` instead of regular function application? The reason is that `$` is a right-associative (`infixr`), low precedence (`0`) operator. This means that `$` allows us to remove sets of parentheses for deeply-nested applications.
658
-
659
-
For example, the above nested function application to create an `AddressBook` with three entries:
660
+
The `apply` function takes another function (of type `(a -> b)`) as its first argument and a value (of type `a`) as its second argument, then calls that function with that value. If it seems like this function doesn't contribute anything meaningful, you are absolutely correct! Your program is logically identical without it (see [referential transparency](https://en.wikipedia.org/wiki/Referential_transparency)). The syntactic utility of this function comes from the special properties assigned to its infix operator. `$` is a right-associative (`infixr`), low precedence (`0`) operator, which lets us remove sets of parentheses for deeply-nested applications.
660
661
662
+
Another parens-busting opportunity for the `$` operator is in our earlier `findEntry` function:
661
663
```haskell
662
-
book3 = insertEntry john (insertEntry peggy (insertEntry ned emptyBook))
663
-
```
664
-
665
-
becomes (arguably) easier to read when expressed using `$`:
666
-
667
-
```haskell
668
-
book6 = insertEntry john $ insertEntry peggy $ insertEntry ned emptyBook
664
+
findEntry firstName lastName book =head$filter filterEntry book
669
665
```
666
+
We'll see an even more elegant way to rewrite this line with "function composition" in the next section.
670
667
671
-
Wrapping an infix operator in parentheses lets you use it as a prefix function:
668
+
If you'd like to use a concise infix operator alias as a prefix function, you can surround it in parenthesis:
672
669
673
670
```text
674
671
> 8 + 3
@@ -678,22 +675,25 @@ Wrapping an infix operator in parentheses lets you use it as a prefix function:
678
675
11
679
676
```
680
677
681
-
Alternatively, operators can be partially applied by surrounding them with parentheses and using `_` as an operand in an [operator section](https://github.com/purescript/documentation/blob/master/language/Syntax.md#operator-sections):
678
+
Alternatively, operators can be partially applied by surrounding the expression with parentheses and using `_` as an operand in an [operator section](https://github.com/purescript/documentation/blob/master/language/Syntax.md#operator-sections). You can think of this as a more convenient way to create simple anonymous functions (although in the below example, we're then binding that anonymous function to a name, so it's not so anonymous anymore):
682
679
683
680
```text
684
681
> add3 = (3 + _)
685
682
> add3 2
686
683
5
687
684
```
688
685
689
-
To summarize, the following are equivalent definitions of a function that adds `5` to its argument:
686
+
To summarize, the following are equivalent definitions of a function that adds `5` to its argument:
690
687
691
688
```haskell
692
689
add5 x =5+ x
693
690
add5 x = add 5 x
694
691
add5 x =(+)5 x
695
692
add5 x =5`add` x
696
693
add5 = add 5
694
+
add5 =\x ->5+ x
695
+
add5 = (5+ _)
696
+
add5 x =5 `(+)` x -- Yo Dawg, I herd you like infix, so we put infix in your infix!
697
697
```
698
698
699
699
## Function Composition
@@ -749,3 +749,4 @@ In this chapter, we covered several new functional programming concepts:
749
749
- Using techniques like eta conversion and function composition to refactor code into a clear specification.
750
750
751
751
In the following chapters, we'll build on these ideas.
0 commit comments