@@ -5,4 +5,108 @@ title: Appar
5
5
6
6
{% include toc.html %}
7
7
8
- https://hackage.haskell.org/package/appar
8
+ [ Appar] ( https://hackage.haskell.org/package/appar ) is different from the other
9
+ libraries such that, they are monadic, while ` appar ` is applicative.
10
+ See [ this] ( https://stackoverflow.com/a/7863380/1599054 ) to have a good explanation
11
+ between the two.
12
+
13
+ # Definition
14
+
15
+ Let's start with the definition:
16
+
17
+ ``` haskell
18
+ data MkParser inp a = P {
19
+ runParser :: inp -> (Maybe a , inp )
20
+ }
21
+ ```
22
+
23
+ It really looks like `attoparsec` 's `ZeptoT `, except that the `Monad ` is inside
24
+ the result.
25
+
26
+ Let's see the instances:
27
+
28
+ ```haskell
29
+ instance Functor (MkParser inp ) where
30
+ f `fmap` p = return f <*> p
31
+
32
+ instance Applicative (MkParser inp ) where
33
+ pure a = P $ \ bs -> (Just a, bs)
34
+ (<*>) = ap
35
+
36
+ instance Alternative (MkParser inp ) where
37
+ empty = mzero
38
+ (<|>) = mplus
39
+
40
+ instance Monad (MkParser inp ) where
41
+ return = pure
42
+ p >>= f = P $ \ bs -> case runParser p bs of
43
+ (Nothing , bs') -> (Nothing , bs')
44
+ (Just a, bs') -> runParser (f a) bs'
45
+
46
+ instance MonadPlus (MkParser inp ) where
47
+ mzero = P $ \ bs -> (Nothing , bs)
48
+ p `mplus` q = P $ \ bs -> case runParser p bs of
49
+ (Nothing , bs') -> runParser q bs'
50
+ (Just a, bs') -> (Just a, bs')
51
+ ```
52
+
53
+ One thing surprising is the ` Monad ` instance for an applicative parser, we can
54
+ conclude that the '` Applicative ` ness' of the library cames from the lack of
55
+ shortcut, more than the implemented solution.
56
+
57
+ # Construction
58
+
59
+ How are parsers built:
60
+
61
+ ``` haskell
62
+ class Eq inp => Input inp where
63
+ -- | The head function for input
64
+ car :: inp -> Char
65
+ -- | The tail function for input
66
+ cdr :: inp -> inp
67
+ -- | The end of input
68
+ nil :: inp
69
+ -- | The function to check the end of input
70
+ isNil :: inp -> Bool
71
+
72
+ satisfy :: Input inp => (Char -> Bool ) -> MkParser inp Char
73
+ satisfy predicate = P sat
74
+ where
75
+ sat bs
76
+ | isNil bs = (Nothing , nil)
77
+ | predicate b = (Just b, bs')
78
+ | otherwise = (Nothing , bs)
79
+ where
80
+ b = car bs
81
+ bs' = cdr bs
82
+ ```
83
+
84
+ A bit abstract (and a bit lisp-like), but without surprises.
85
+
86
+ Anothor interesting one:
87
+
88
+ ``` haskell
89
+ try :: MkParser inp a -> MkParser inp a
90
+ try p = P $ \ bs -> case runParser p bs of
91
+ (Nothing , _ ) -> (Nothing , bs)
92
+ (Just a, bs') -> (Just a, bs')
93
+ ```
94
+
95
+ As expected: the parser is ran, if it succeeds, the input is consumer, or the
96
+ original input is returned.
97
+
98
+ # Running the parser
99
+
100
+ As we can expect, running the pparser will only consist in getting the computed
101
+ result:
102
+
103
+ ``` haskell
104
+ parse :: Input inp => MkParser inp a -> inp -> Maybe a
105
+ parse p bs = fst (runParser p bs)
106
+ ```
107
+
108
+ # Conclusion
109
+
110
+ ` appar ` is really simple, but it is unique in the sense that it prevent
111
+ context-dependant parsing.
112
+
0 commit comments