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: _chapters/haskell3.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -869,7 +869,7 @@ This will allow us to make more functions point-free
869
869
870
870
```haskell
871
871
square::Numa=>a=>a
872
-
square = a * a
872
+
square a = a * a
873
873
```
874
874
875
875
```haskell
@@ -888,7 +888,7 @@ class Applicative f => Alternative (f :: * -> *) where
888
888
(<|>)::fa->fa->fa
889
889
```
890
890
891
-
`empty`:This function represents a computation with *no result or a failure*.It serves as the identity element.For different data types that are instances ofAlternative, `empty` represents an empty container or a *failed computation*, depending on the context.
891
+
`empty`:This function represents a computation with either*no result,or a failure*.It serves as the identity element.For different data types that are instances ofAlternative, `empty` represents an empty container or a *failed computation*, depending on the context.
892
892
893
893
`(<|>)`:The `<|>` operator combines two computations, and it’s used to express alternatives.It takes two computations of the same typeand returns a computation that will produce a result from the first computation if it succeeds, orif it fails, it will produce a result from the second computation.This operator allows you to handle branching logic and alternative paths in your code.
Copy file name to clipboardExpand all lines: _chapters/haskell4.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -104,7 +104,7 @@ Note that since the `(+)` operator is associative—a+(b+c) = (a+b)+c—`foldr`
104
104
105
105
## Monoid
106
106
107
-
In the example fold above, we provide the `(+)` function to tell `foldl` how to aggregate elements of the list. There is also a typeclass for things that are “automatically aggregatable” or “concatenatable” called `Monoid` which declares a general function for `mappend` combining two `Monoid`s into one, a `mempty` value such that any Monoid `mappend`'ed with `mempty` is itself, and a concatenation function for lists of `Monoid` called `mconcat`.
107
+
In the example fold above, we provide the `(+)` function to tell `foldl` how to aggregate elements of the list. There is also a typeclass for things that are “automatically aggregable” or “concatenatable” called `Monoid` which declares a general function for `mappend` combining two `Monoid`s into one, a `mempty` value such that any Monoid `mappend`'ed with `mempty` is itself, and a concatenation function for lists of `Monoid` called `mconcat`.
We make a data type aggregatable by instancing `Monoid` and providing definitions for the functions `mappend` and `mempty`. For `Sum` these will be `(+)` and `0` respectively.
136
+
We make a data type aggregable by instancing `Monoid` and providing definitions for the functions `mappend` and `mempty`. For `Sum` these will be `(+)` and `0` respectively.
137
137
Lists are also themselves Monoidal, with `mappend` defined as an alias for list concatenation `(++)`, and mempty as `[]`. Thus, we can:
Copy file name to clipboardExpand all lines: _chapters/parsercombinators.md
+51Lines changed: 51 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,6 +25,57 @@ The parser combinator discussed here is based on one developed by Tony Morris an
25
25
26
26
You can play with the example and the various parser bits and pieces in [this online playground](https://replit.com/@tgdwyer/Parser-Examples).
27
27
28
+
## Why do we need Monads ?
29
+
30
+
Consider the task of parsing the following string:
31
+
32
+
```haskell
33
+
5abcdefg
34
+
```
35
+
36
+
In this example, the number `5` specifies how many characters should be parsed from the rest of the string.
37
+
The goal is to obtain the result:
38
+
39
+
```haskell
40
+
Just ("fg", "abcde")
41
+
```
42
+
43
+
The parser should first read the number 5, then use that value to determine how many characters to extract `"abcde"`, leaving the remainder `"fg"` unparsed. The key question here is: Can we achieve this using only `Functor` and `Applicative`?
44
+
45
+
The answer is no. Both of these abstractions allow us to combine independent computations, but they do not allow one computation to depend on the result of another. Using a Monad, we can **sequence** computations where the output of one step influences the next step’s behavior, which is precisely what this parsing task requires.
46
+
47
+
So, if we have these two parsers:
48
+
49
+
```haskell
50
+
parseInt::ParserInt
51
+
parseInt = int
52
+
53
+
parseNCharacters::Int->ParserString
54
+
parseNCharacters 0=pure""
55
+
parseNCharacters n = liftA2 (:) char (parseNCharacters (n-1))
56
+
```
57
+
58
+
We want a way to combine these two parsers — first run `parseInt`, then pass its result to `parseNCharacters`. Let’s imagine a new operator that could do this:
When we generalize this `newOperator` idea, to any container, we get:
72
+
73
+
```haskell
74
+
(>>=)::fa-> (a->fb) ->fb
75
+
```
76
+
77
+
This operator is called `bind`, and it is the core of the `Monad` type class.This is a very powerful concept, it allows you to chain dependent computations —where the output of one step determines the next step.This is exactly why `Monads` go beyond `Functors` and `Applicatives`: they enable sequencing with dependency.
78
+
28
79
## Context-free Grammars and BNF
29
80
30
81
Fundamental to the analysis of human natural language but also to the design of programming languages is the idea of a *grammar*, or a set of rules for how elements of the language may be composed.A context-free grammar (CFG) is one in which the set of rules for what is produced for a given input (*production rules*) completely covers the set of possible input symbols (i.e. there is no additional context required to parse the input).Backus-NaurForm (orBNF) is a notation that has become standard for writing CFGs since the 1960s.We will use BNF notation from now on.There are two types of symbols in a CFG:*terminal*and*non-terminal*.InBNF non-terminal symbols are `<nameInsideAngleBrackets>` and can be converted into a mixture of terminals and/or nonterminals by production rules:
0 commit comments