This repository has been archived by the owner on Jul 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLab05transformers.hs
143 lines (121 loc) · 4.02 KB
/
Lab05transformers.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
module Lab05transformers where
import Control.Monad.Trans.State
import Data.Char ( digitToInt
, isDigit
)
import Control.Monad.Trans.Class ( MonadTrans(..) )
import Control.Monad ( MonadPlus(..) )
import Control.Applicative ( Alternative(..)
, many
)
import Data.Maybe ( fromMaybe )
-- 1.
type Parser a = StateT String Maybe a
runParser :: Parser a -> String -> Maybe (a, String)
runParser = runStateT
-- | item
-- >>> runParser item "ela"
-- Just ('e',"la")
-- >>> runParser item ""
-- Nothing
item :: Parser Char
item = do
(x : xs) <- get
put xs
return x
-- | sat
-- >>> runParser (sat $ flip elem "abc") "ala"
-- Just ('a',"la")
-- >>> runParser (sat $ flip elem "abc") "ela"
-- Nothing
sat :: (Char -> Bool) -> Parser Char
sat f = do
x <- item
if f x then return x else fail "Condition not satisfied"
-- | many (imported from Applicative) and many1
-- >>> runParser (many $ char 'e') "eeela"
-- Just ("eee","la")
-- >>> runParser (many $ char 'e') "ala"
-- Just ("","ala")
-- >>> runParser (many1 $ char 'e') "eeela"
-- Just ("eee","la")
-- >>> runParser (many1 $ char 'e') "ala"
-- Nothing
many1 :: Parser a -> Parser [a]
many1 p = (:) <$> p <*> many p
-- | pDigit
-- >>> runParser pDigit "123"
-- Just (1,"23")
-- >>> runParser pDigit "ela"
-- Nothing
pDigit :: Parser Int
pDigit = digitToInt <$> sat isDigit
-- | pNat
-- >>> runParser pNat "123ela"
-- Just (123,"ela")
-- >>> runParser pNat "ela"
-- Just (0,"ela")
pNat :: Parser Int
pNat = sum . zipWith ((*) . (10 ^)) [0 ..] . reverse <$> pDigits
-- Additional functions
-- >>> runParser pDigits "123ela"
-- Just ([1,2,3],"ela")
-- >>> runParser pDigits "ela"
-- Just ([],"ela")
pDigits :: Parser [Int]
pDigits = many pDigit
-- | pDigit1
-- > runParser pDigit1 "123"
-- Just (1,"23")
-- > runParser pDigit1 "ela"
-- Nothing
pDigit1 :: Parser Int
pDigit1 = do
x <- item
if isDigit x then return $ digitToInt x else fail ""
-- | char
-- > runParser (char 'e') "ela"
-- Just ('e',"la")
-- > runParser (char 'f') "ela"
-- Nothing
char :: Char -> Parser Char
char = sat . (==)
-- 2.
newtype IdentityT f a = IdentityT {runIdentityT :: f a}
instance Functor m => Functor (IdentityT m) where
fmap f = IdentityT . fmap f . runIdentityT
instance (Monad m) => Monad (IdentityT m) where
(>>=) x f = IdentityT (runIdentityT x >>= runIdentityT . f)
instance MonadTrans IdentityT where
lift = IdentityT
instance MonadPlus m => MonadPlus (IdentityT m)
-- Needed for Monad
instance Applicative m => Applicative (IdentityT m) where
pure = IdentityT . pure
(<*>) f x = IdentityT $ runIdentityT f <*> runIdentityT x
-- Needed for MonadPlus
instance Alternative m => Alternative (IdentityT m) where
empty = IdentityT empty
(<|>) x y = IdentityT $ runIdentityT x <|> runIdentityT y
-- 3.
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
instance Functor m => Functor (MaybeT m) where
fmap f = MaybeT . fmap (fmap f) . runMaybeT
-- ^ Maybe is a Functor instance
instance Monad m => Monad (MaybeT m) where
(>>=) x f =
MaybeT $ runMaybeT x >>= foldr (const . runMaybeT . f) (return Nothing)
-- ^ Maybe is a Foldable instance
instance MonadTrans MaybeT where
lift = MaybeT . (Just <$>)
instance Monad m => MonadPlus (MaybeT m)
-- Needed for Monad
instance Applicative m => Applicative (MaybeT m) where
pure = MaybeT . pure . Just
(<*>) f x = MaybeT $ (<*>) <$> runMaybeT f <*> runMaybeT x
-- ^ Maybe is an Applicative instance
-- Needed for Alternative
instance Applicative m => Alternative (MaybeT m) where
empty = MaybeT $ pure Nothing
(<|>) x y = MaybeT $ (<|>) <$> runMaybeT x <*> runMaybeT y
-- ^ Maybe is an Alternative instance