-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmonads_1.hs
More file actions
95 lines (75 loc) · 2.38 KB
/
monads_1.hs
File metadata and controls
95 lines (75 loc) · 2.38 KB
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
module Monads1 where
--import Prelude hiding (Just, Nothing, Maybe)
import Prelude hiding ((>>=))
inc :: [Int] -> [Int]
inc [] = []
inc (x:xs) = (x + 1) : inc xs
sqr :: [Int] -> [Int]
sqr [] = []
sqr (x:xs) = x^2 : sqr xs
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = f x : map' f xs
inc' = map' (+1)
sqr' = map' (^2)
data Expr = Val Int | Div Expr Expr
--simple lang of expressions with division operator
eval :: Expr -> Int
eval (Val n) = n
eval (Div x y) = eval x `div` eval y
--but if we divide by 0, it throws an error
--data Maybe a = Nothing | Just a
safediv :: Int -> Int -> Maybe Int
safediv x y = if y == 0 then Nothing else Just (x `div` y)
eval' :: Expr -> Maybe Int
eval' (Val n) = Just n
eval' (Div x y) = case eval' x of
Nothing -> Nothing
Just n -> case eval' y of
Nothing -> Nothing
Just m -> safediv n m
test1 = eval (Div (Val 8) (Val 4))
test2 = eval (Div (Val 10) (Val 0))
test3 = eval' (Div (Val 8) (Val 4))
test4 = eval' (Div (Val 10) (Val 0))
sequ :: Maybe a -> Maybe b -> Maybe (a, b)
sequ Nothing _ = Nothing
sequ _ Nothing = Nothing
sequ (Just x) (Just y) = Just (x, y)
apply :: (a -> Maybe b) -> Maybe a -> Maybe b
apply f Nothing = Nothing
apply f (Just x) = f x
eval'' :: Expr -> Maybe Int
eval'' (Val n) = Just n
eval'' (Div x y) = apply f (eval'' x `sequ` eval'' y)
where f (n, m) = safediv n m
test5 = eval'' (Div (Val 8) (Val 4))
--sequencing operator "then"
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
(Just x) >>= f = f x
-- evaluate x and call it n, evaluate y and call it m, perform divison
eval''' :: Expr -> Maybe Int
eval''' (Val n) = Just n
eval''' (Div x y) = eval''' x >>= (\n -> eval''' y >>= (\m -> safediv n m))
test6 = eval''' (Div (Val 8) (Val 4))
test7 = eval''' (Div (Div (Val 8) (Val 2)) (Val 2))
-- generally a typical structure built using >>= operator has the following
-- structure:
-- m1 >>= \x1 ->
-- m2 >>= \x2 ->
-- ..
-- mn >>= \xn ->
-- f x1 x2 .. xn
--which can be written in a cleaner form:
--do x1 <- m1
-- x2 <- m2
-- ..
-- xn <- mn
-- f x1 x2 .. xn
eval'''' :: Expr -> Maybe Int
eval'''' (Val n) = Just n
eval'''' (Div x y) = do n <- eval'''' x
m <- eval'''' y
safediv n m
test8 = eval'''' (Div (Val 8) (Val 4))