-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMonad.hs
142 lines (125 loc) · 3.1 KB
/
Monad.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
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Monad where
import Applicative (Applicative)
import qualified Applicative as A
import Core
import ExactlyOne (ExactlyOne (..))
import qualified ExactlyOne as EO
import qualified Functor as F
import List (List (..))
import qualified List as L
import Optional (Optional (..))
import qualified Optional as O
import qualified Prelude as P ((=<<))
-- | All instances of the `Monad` type-class must satisfy one law. This law
-- is not checked by the compiler. This law is given as:
--
-- * The law of associativity
-- `∀f g x. g =<< (f =<< x) ≅ ((g =<<) . f) =<< x`
class (Applicative f) => Monad f where
-- Pronounced, bind.
(=<<) :: (a -> f b) -> f a -> f b
infixr 1 =<<
-- | Binds a function on the ExactlyOne monad.
--
-- >>> (\x -> ExactlyOne(x+1)) =<< ExactlyOne 2
-- ExactlyOne 3
instance Monad ExactlyOne where
(=<<) :: (a -> ExactlyOne b) -> ExactlyOne a -> ExactlyOne b
(=<<) = EO.bindExactlyOne
-- | Binds a function on a List.
--
-- >>> (\n -> n :. n :. Nil) =<< (1 :. 2 :. 3 :. Nil)
-- [1,1,2,2,3,3]
instance Monad List where
(=<<) :: (a -> List b) -> List a -> List b
(=<<) = L.flatMap
-- | Binds a function on an Optional.
--
-- >>> (\n -> Full (n + n)) =<< Full 7
-- Full 14
instance Monad Optional where
(=<<) :: (a -> Optional b) -> Optional a -> Optional b
(=<<) = O.bindOptional
-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- (7 + 10) * 7 = 119
instance Monad ((->) t) where
(=<<) :: (a -> (->) t b) -> (->) t a -> (->) t b
f =<< g = \x -> f (g x) x
-- | Witness that all things with (=<<) and (<$>) also have (<*>).
--
-- >>> ExactlyOne (+10) <**> ExactlyOne 8
-- ExactlyOne 18
--
-- >>> (+1) :. (*2) :. Nil <**> 1 :. 2 :. 3 :. Nil
-- [2,3,4,2,4,6]
--
-- >>> Full (+8) <**> Full 7
-- Full 15
--
-- >>> Empty <**> Full 7
-- Empty
--
-- >>> Full (+8) <**> Empty
-- Empty
--
-- >>> ((+) <**> (+10)) 3
-- 16
--
-- >>> ((+) <**> (+5)) 3
-- 11
--
-- >>> ((+) <**> (+5)) 1
-- 7
--
-- >>> ((*) <**> (+10)) 3
-- 39
--
-- >>> ((*) <**> (+2)) 3
-- 15
(<**>) :: (Monad f) => f (a -> b) -> f a -> f b
(<**>) = (A.<*>)
infixl 4 <**>
-- | Flattens a combined structure to a single structure.
--
-- >>> join ((1 :. 2 :. 3 :. Nil) :. (1 :. 2 :. Nil) :. Nil)
-- [1,2,3,1,2]
--
-- >>> join (Full Empty)
-- Empty
--
-- >>> join (Full (Full 7))
-- Full 7
--
-- >>> join (+) 7
-- 14
join :: (Monad f) => f (f a) -> f a
join = (=<<) id
-- | Implement a flipped version of @(=<<)@, however, use only
-- @join@ and @(<$>)@.
-- Pronounced, bind flipped.
--
-- >>> ((+10) >>= (*)) 7
-- 119
(>>=) :: (Monad f) => f a -> (a -> f b) -> f b
a >>= f = join (f F.<$> a)
infixl 1 >>=
-- | Implement composition within the @Monad@ environment.
-- Pronounced, kleisli composition.
--
-- >>> ((\n -> n :. n :. Nil) <=< (\n -> n+1 :. n+2 :. Nil)) 1
-- [2,2,3,3]
(<=<) :: (Monad f) => (b -> f c) -> (a -> f b) -> a -> f c
f <=< g = \x -> f =<< g x
infixr 1 <=<
-----------------------
-- SUPPORT LIBRARIES --
-----------------------
instance Monad IO where
(=<<) =
(P.=<<)