@@ -15,8 +15,15 @@ module Control.Monad.Free
15
15
16
16
import Prelude
17
17
18
+ import Control.Apply (lift2 )
18
19
import Control.Monad.Rec.Class (class MonadRec , Step (..), tailRecM )
20
+ import Control.Monad.Trans.Class (class MonadTrans )
21
+ import Data.Either (Either (..))
22
+ import Data.Eq (class Eq1 , eq1 )
19
23
import Data.Exists (Exists , mkExists , runExists )
24
+ import Data.Foldable (class Foldable , foldMap , foldl , foldr )
25
+ import Data.Ord (class Ord1 , compare1 )
26
+ import Data.Traversable (class Traversable , traverse )
20
27
import Unsafe.Coerce (unsafeCoerce )
21
28
22
29
foreign import data UnsafeBoundValue :: Type
@@ -27,6 +34,83 @@ data Free f a
27
34
= Pure a
28
35
| Bind (f UnsafeBoundValue ) (FreeBinds f UnsafeBoundValue a )
29
36
37
+ instance eqFree :: (Functor f , Eq1 f , Eq a ) => Eq (Free f a ) where
38
+ eq x y = case resume' x, resume' y of
39
+ Left fa, Left fb -> eq1 fa fb
40
+ Right a, Right b -> eq a b
41
+ _, _ -> false
42
+
43
+ instance ordFree :: (Functor f , Ord1 f , Ord a ) => Ord (Free f a ) where
44
+ compare x y = case resume' x, resume' y of
45
+ Left fa, Left fb -> compare1 fa fb
46
+ Left _, _ -> LT
47
+ _, Left _ -> GT
48
+ Right a, Right b -> compare a b
49
+
50
+ instance eq1Free :: (Functor f , Eq1 f ) => Eq1 (Free f ) where
51
+ eq1 = eq
52
+
53
+ instance ord1Free :: (Functor f , Ord1 f , Ord a ) => Ord1 (Free f ) where
54
+ compare1 = compare
55
+
56
+ instance functorFree :: Functor (Free f ) where
57
+ map f (Pure a) = Pure (f a)
58
+ map f (Bind a bs) = Bind a (Node (unsafeCoerce bs) (Leaf (Pure <<< unsafeCoerce f)))
59
+
60
+ instance applyFree :: Apply (Free f ) where
61
+ apply = ap
62
+
63
+ instance applicativeFree :: Applicative (Free f ) where
64
+ pure = Pure
65
+
66
+ instance bindFree :: Bind (Free f ) where
67
+ bind (Pure a) k = k a
68
+ bind (Bind a bs) k = Bind a (Node (unsafeCoerce bs) (Leaf (unsafeCoerce k)))
69
+
70
+ instance monadFree :: Monad (Free f )
71
+
72
+ instance monadTransFree :: MonadTrans Free where
73
+ lift = lift
74
+
75
+ instance monadRecFree :: MonadRec (Free f ) where
76
+ tailRecM k a = k a >>= case _ of
77
+ Loop b -> tailRecM k b
78
+ Done r -> pure r
79
+
80
+ instance foldableFree :: (Functor f , Foldable f ) => Foldable (Free f ) where
81
+ foldMap f = go
82
+ where
83
+ go = resume' >>> case _ of
84
+ Left fa -> foldMap go fa
85
+ Right a -> f a
86
+
87
+ foldl f = go
88
+ where
89
+ go r = resume' >>> case _ of
90
+ Left fa -> foldl go r fa
91
+ Right a -> f r a
92
+
93
+ foldr f = go
94
+ where
95
+ go r = resume' >>> case _ of
96
+ Left fa -> foldr (flip go) r fa
97
+ Right a -> f a r
98
+
99
+ instance traversableFree :: Traversable f => Traversable (Free f ) where
100
+ traverse f = go
101
+ where
102
+ go = resume' >>> case _ of
103
+ Left fa -> join <<< lift <$> traverse go fa
104
+ Right a -> pure <$> f a
105
+
106
+ sequence tma = traverse identity tma
107
+
108
+ instance semigroupFree :: Semigroup a => Semigroup (Free f a ) where
109
+ append = lift2 append
110
+
111
+ instance monoidFree :: Monoid a => Monoid (Free f a ) where
112
+ mempty = pure mempty
113
+
30
114
data FreeView f a b
31
115
= PureView a
32
116
| BindView (f b ) (b -> Free f a )
@@ -39,36 +123,26 @@ data FreeBinds f a b
39
123
data FreeCons f a b
40
124
= FreeCons (a -> Free f UnsafeBoundValue ) (FreeBinds f UnsafeBoundValue b )
41
125
126
+ -- | Lift an impure value described by the generating type constructor `f` into
127
+ -- | the free monad.
42
128
lift :: forall f a . f a -> Free f a
43
129
lift f = Bind (unsafeCoerce f) (unsafeCoerce (Leaf Pure ))
44
130
131
+ -- | Add a layer.
45
132
roll :: forall f a . f (Free f a ) -> Free f a
46
133
roll f = Bind (unsafeCoerce f) (unsafeCoerce (Leaf \a -> a))
47
134
135
+ -- | Suspend a value given the applicative functor `f` into the free monad.
48
136
suspend :: forall f a . Applicative f => Free f a -> Free f a
49
- suspend = roll <<< pure
137
+ suspend f = roll ( pure f)
50
138
139
+ -- | Use a natural transformation to change the generating type constructor of a
140
+ -- | free monad.
51
141
hoist :: forall f g . (f ~> g ) -> Free f ~> Free g
52
142
hoist nat = case _ of
53
143
Pure a -> Pure a
54
144
Bind f k -> Bind (nat f) (Hoist (unsafeCoerce nat) (unsafeCoerce k))
55
145
56
- instance functorFree :: Functor (Free f ) where
57
- map f (Pure a) = Pure (f a)
58
- map f (Bind a bs) = Bind a (Node (unsafeCoerce bs) (Leaf (Pure <<< unsafeCoerce f)))
59
-
60
- instance applyFree :: Apply (Free f ) where
61
- apply = ap
62
-
63
- instance applicativeFree :: Applicative (Free f ) where
64
- pure = Pure
65
-
66
- instance bindFree :: Bind (Free f ) where
67
- bind (Pure a) k = k a
68
- bind (Bind a bs) k = Bind a (Node (unsafeCoerce bs) (Leaf (unsafeCoerce k)))
69
-
70
- instance monadFree :: Monad (Free f )
71
-
72
146
resume
73
147
:: forall f a r
74
148
. (a -> r )
@@ -99,34 +173,20 @@ resume pure' bind' = case _ of
99
173
Hoist nat' bs' ->
100
174
go2 (nat <<< nat') bs' x
101
175
102
- uncons :: forall f a b x . FreeBinds f a x -> FreeBinds f x b -> FreeCons f a b
103
- uncons = go1
104
- where
105
- go1 :: forall a' b' x' . FreeBinds f a' x' -> FreeBinds f x' b' -> FreeCons f a' b'
106
- go1 l r = case l of
107
- Leaf k -> FreeCons (unsafeCoerce k) (unsafeCoerce r)
108
- Node l' r' -> go1 l' (Node (unsafeCoerce r') (unsafeCoerce r))
109
- Hoist nat l' -> go2 nat l' r
110
-
111
- go2 :: forall g a' b' x' . (UnsafeBoundF ~> g ) -> FreeBinds UnsafeBoundF a' x' -> FreeBinds g x' b' -> FreeCons g a' b'
112
- go2 nat l r = case l of
113
- Leaf k -> FreeCons (hoist nat <$> unsafeCoerce k) (unsafeCoerce r)
114
- Node l' r' -> go2 nat l' (Node (Hoist nat (unsafeCoerce r')) (unsafeCoerce r))
115
- Hoist nat' n -> go2 (nat <<< nat') n r
116
-
117
- view :: forall f a . Free f a -> Exists (FreeView f a )
118
- view = resume (mkExists <<< PureView ) \a b -> mkExists (BindView a b)
119
-
120
176
run :: forall f m a . Functor f => Monad m => (f (Free f a ) -> m (Free f a )) -> Free f a -> m a
121
177
run next = go where go = resume pure (\f k -> next (k <$> f) >>= go)
122
178
179
+ -- | Run a free monad with a function mapping a functor `f` to a tail-recursive
180
+ -- | monad `m`. See the `MonadRec` type class for more details.
123
181
runRec :: forall f m a . Functor f => MonadRec m => (f (Free f a ) -> m (Free f a )) -> Free f a -> m a
124
182
runRec next = tailRecM go <<< view
125
183
where
126
184
go = runExists case _ of
127
185
PureView a -> pure $ Done a
128
186
BindView f k -> Loop <<< view <$> next (k <$> f)
129
187
188
+ -- | Run a free monad with a function that unwraps a single layer of the functor
189
+ -- | `f` at a time.
130
190
runPure :: forall f a . Functor f => (f (Free f a ) -> Free f a ) -> Free f a -> a
131
191
runPure next = go
132
192
where
@@ -135,12 +195,39 @@ runPure next = go
135
195
PureView a -> a
136
196
BindView f k -> go (next (k <$> f))
137
197
198
+ -- | Run a free monad with a natural transformation from the type constructor `f`
199
+ -- | to the monad `m`, which can be some other Free monad. If you need tail
200
+ -- | recursion for stack safety, see `interpretRec`.
138
201
interpret :: forall f m a . Monad m => (f ~> m ) -> Free f a -> m a
139
202
interpret next = go where go = resume pure (\f k -> next f >>= k >>> go)
140
203
204
+ -- | Run a free monad with a natural transformation from the type constructor `f`
205
+ -- | to the tail-recursive monad `m`. See the `MonadRec` type class for more
206
+ -- | details.
141
207
interpretRec :: forall f m a . MonadRec m => (f ~> m ) -> Free f a -> m a
142
208
interpretRec nat = tailRecM go <<< view
143
209
where
144
210
go = runExists case _ of
145
211
PureView a -> pure $ Done a
146
212
BindView f k -> Loop <<< view <<< k <$> nat f
213
+
214
+ resume' :: forall f a . Functor f => Free f a -> Either (f (Free f a )) a
215
+ resume' = resume Right (\g i -> Left (map i g))
216
+
217
+ uncons :: forall f a b x . FreeBinds f a x -> FreeBinds f x b -> FreeCons f a b
218
+ uncons = go1
219
+ where
220
+ go1 :: forall a' b' x' . FreeBinds f a' x' -> FreeBinds f x' b' -> FreeCons f a' b'
221
+ go1 l r = case l of
222
+ Leaf k -> FreeCons (unsafeCoerce k) (unsafeCoerce r)
223
+ Node l' r' -> go1 l' (Node (unsafeCoerce r') (unsafeCoerce r))
224
+ Hoist nat l' -> go2 nat l' r
225
+
226
+ go2 :: forall g a' b' x' . (UnsafeBoundF ~> g ) -> FreeBinds UnsafeBoundF a' x' -> FreeBinds g x' b' -> FreeCons g a' b'
227
+ go2 nat l r = case l of
228
+ Leaf k -> FreeCons (hoist nat <$> unsafeCoerce k) (unsafeCoerce r)
229
+ Node l' r' -> go2 nat l' (Node (Hoist nat (unsafeCoerce r')) (unsafeCoerce r))
230
+ Hoist nat' n -> go2 (nat <<< nat') n r
231
+
232
+ view :: forall f a . Free f a -> Exists (FreeView f a )
233
+ view = resume (mkExists <<< PureView ) \a b -> mkExists (BindView a b)
0 commit comments