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
+69-33Lines changed: 69 additions & 33 deletions
Original file line number
Diff line number
Diff line change
@@ -579,18 +579,66 @@ Note that, just like for top-level declarations, it was not necessary to specify
579
579
580
580
## Infix Function Application
581
581
582
-
Most of the functions discussed so far used _prefix_ function application, where the function name was put _before_ the arguments. For example, when using the `findEntry` function to search an `AddressBook`, one might write:
582
+
Most of the functions discussed so far used _prefix_ function application, where the function name was put _before_ the arguments. For example, when using the `insertEntry` function to add an `Entry` (`john`) to an empty `AddressBook`, we might write:
583
583
584
-
```text
585
-
> findEntry "John" "Smith" addressBook
584
+
```haskell
585
+
>book1 = insertEntry john emptyBook
586
586
```
587
587
588
-
However, this chapter has also included examples of _infix_functions, such as the `==`function in the definition of `filterEntry`, where the function is put _between_ the arguments. These infix operators are actually defined in the PureScript source as infix aliases for their underlying implementations. For example, `==` is defined as an alias for the prefix `eq` function with the line:
588
+
However, this chapter has also included examples of _infix_[binary operators](https://github.com/purescript/documentation/blob/master/language/Syntax.md#binary-operators), such as the `==`operator in the definition of `filterEntry`, where the operator is put _between_ the two arguments. These infix operators are actually defined in the PureScript source as infix aliases for their underlying _prefix_implementations. For example, `==` is defined as an infix alias for the prefix `eq` function with the line:
589
589
590
590
```haskell
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`.
595
+
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
+
598
+
```text
599
+
> mod 8 3
600
+
2
601
+
```
602
+
603
+
This is fine, but doesn't line up with common usage (in conversation, one might say "eight mod three"). Wrapping a prefix function in backticks (\`) lets you use that it in infix position as an operator, e.g.,
604
+
605
+
```text
606
+
> 8 `mod` 3
607
+
2
608
+
```
609
+
610
+
In the same way, wrapping `insertEntry` in backticks turns it into an infix operator, such that `book1` and `book2` below are equivalent:
611
+
612
+
```haskell
613
+
book1 = insertEntry john emptyBook
614
+
book2 = john `insertEntry` emptyBook
615
+
```
616
+
617
+
We can make an `AddressBook` with multiple entries by using multiple applications of `insertEntry` as a prefix function (`book3`) or as an infix operator (`book4`) as shown below:
618
+
619
+
```haskell
620
+
book3 = insertEntry john (insertEntry peggy (insertEntry ned emptyBook))
621
+
book4 = john `insertEntry` (peggy `insertEntry` (ned `insertEntry` emptyBook))
622
+
```
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`:
625
+
626
+
```haskell
627
+
infixr5 insertEntry as ++
628
+
```
629
+
630
+
This new operator lets us rewrite the above `book4` example as:
631
+
632
+
```haskell
633
+
book6 = john ++ (peggy ++ (ned ++ emptyBook))
634
+
```
635
+
636
+
and the right associativity of our new `++` operator lets us get rid of the parentheses without changing the meaning:
637
+
638
+
```haskell
639
+
book6 = john ++ peggy ++ ned ++ emptyBook
640
+
```
641
+
594
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.
595
643
596
644
This is equivalent to the usual application `head (filter filterEntry book)`
@@ -606,60 +654,48 @@ infixr 0 apply as $
606
654
607
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`.
608
656
609
-
But why would we want to use `$` instead of regular function application? The reason is that `$` is a right-associative, low precedence operator. This means that `$` allows us to remove sets of parentheses for deeply-nested applications.
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.
610
658
611
-
For example, the following nested function application, which finds the street in the address of an employee's boss:
659
+
For example, the above nested function application to create an `AddressBook` with three entries:
612
660
613
661
```haskell
614
-
_.street (_.address (_.boss employee))
662
+
book3 = insertEntry john (insertEntry peggy (insertEntry ned emptyBook))
615
663
```
616
664
617
665
becomes (arguably) easier to read when expressed using `$`:
618
666
619
667
```haskell
620
-
_.street $ _.address $ _.boss employee
668
+
book6 = insertEntry john $ insertEntry peggy $ insertEntry ned emptyBook
621
669
```
622
670
623
-
Note that neither of the above examples is idiomatic PureScript. Real-world code is more likely to express this as:
624
-
```haskell
625
-
(boss employee).address.street
626
-
```
627
-
or
628
-
```haskell
629
-
_.boss.address.street employee
630
-
```
671
+
Wrapping an infix operator in parentheses lets you use it as a prefix function:
631
672
632
-
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:
633
-
```text
634
-
> mod 8 3
635
-
2
636
-
```
637
-
This is fine, but doesn't line up with common usage. Wrapping a prefix function in backticks (\`) lets you use a prefix function in infix position as an operator, e.g.,
638
-
```text
639
-
> 8 `mod` 3
640
-
2
641
-
```
642
-
Likewise, wrapping an operator in parentheses lets you use it as a function in prefix position:
643
673
```text
644
674
> 8 + 3
645
675
11
646
676
647
677
> (+) 8 3
648
678
11
649
679
```
650
-
This allows for compact definitions of curried (or partially applied) functions based on infix operator functions, such as the `add2` function below:
651
-
```text
652
-
> add2 = (+) 2
653
-
> add2 4
654
-
6
655
-
```
680
+
656
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):
682
+
657
683
```text
658
684
> add3 = (3 + _)
659
685
> add3 2
660
686
5
661
687
```
662
688
689
+
To summarize, the following are equivalent definitions of a function that adds `5` to its argument:
690
+
691
+
```haskell
692
+
add5 x =5+ x
693
+
add5 x = add 5 x
694
+
add5 x =(+)5 x
695
+
add5 x =5`add` x
696
+
add5 = add 5
697
+
```
698
+
663
699
## Function Composition
664
700
665
701
Just like we were able to simplify the `insertEntry` function by using eta conversion, we can simplify the definition of `findEntry` by reasoning about its arguments.
0 commit comments