Skip to content

Commit 9377e08

Browse files
Re-add doc comments and instances
1 parent 6180532 commit 9377e08

File tree

1 file changed

+122
-35
lines changed

1 file changed

+122
-35
lines changed

src/Control/Monad/Free.purs

Lines changed: 122 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@ module Control.Monad.Free
1515

1616
import Prelude
1717

18+
import Control.Apply (lift2)
1819
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)
1923
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)
2027
import Unsafe.Coerce (unsafeCoerce)
2128

2229
foreign import data UnsafeBoundValue :: Type
@@ -27,6 +34,83 @@ data Free f a
2734
= Pure a
2835
| Bind (f UnsafeBoundValue) (FreeBinds f UnsafeBoundValue a)
2936

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+
30114
data FreeView f a b
31115
= PureView a
32116
| BindView (f b) (b -> Free f a)
@@ -39,36 +123,26 @@ data FreeBinds f a b
39123
data FreeCons f a b
40124
= FreeCons (a -> Free f UnsafeBoundValue) (FreeBinds f UnsafeBoundValue b)
41125

126+
-- | Lift an impure value described by the generating type constructor `f` into
127+
-- | the free monad.
42128
lift :: forall f a. f a -> Free f a
43129
lift f = Bind (unsafeCoerce f) (unsafeCoerce (Leaf Pure))
44130

131+
-- | Add a layer.
45132
roll :: forall f a. f (Free f a) -> Free f a
46133
roll f = Bind (unsafeCoerce f) (unsafeCoerce (Leaf \a -> a))
47134

135+
-- | Suspend a value given the applicative functor `f` into the free monad.
48136
suspend :: forall f a. Applicative f => Free f a -> Free f a
49-
suspend = roll <<< pure
137+
suspend f = roll (pure f)
50138

139+
-- | Use a natural transformation to change the generating type constructor of a
140+
-- | free monad.
51141
hoist :: forall f g. (f ~> g) -> Free f ~> Free g
52142
hoist nat = case _ of
53143
Pure a -> Pure a
54144
Bind f k -> Bind (nat f) (Hoist (unsafeCoerce nat) (unsafeCoerce k))
55145

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-
72146
resume
73147
:: forall f a r
74148
. (a -> r)
@@ -99,34 +173,20 @@ resume pure' bind' = case _ of
99173
Hoist nat' bs' ->
100174
go2 (nat <<< nat') bs' x
101175

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-
120176
run :: forall f m a. Functor f => Monad m => (f (Free f a) -> m (Free f a)) -> Free f a -> m a
121177
run next = go where go = resume pure (\f k -> next (k <$> f) >>= go)
122178

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.
123181
runRec :: forall f m a. Functor f => MonadRec m => (f (Free f a) -> m (Free f a)) -> Free f a -> m a
124182
runRec next = tailRecM go <<< view
125183
where
126184
go = runExists case _ of
127185
PureView a -> pure $ Done a
128186
BindView f k -> Loop <<< view <$> next (k <$> f)
129187

188+
-- | Run a free monad with a function that unwraps a single layer of the functor
189+
-- | `f` at a time.
130190
runPure :: forall f a. Functor f => (f (Free f a) -> Free f a) -> Free f a -> a
131191
runPure next = go
132192
where
@@ -135,12 +195,39 @@ runPure next = go
135195
PureView a -> a
136196
BindView f k -> go (next (k <$> f))
137197

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`.
138201
interpret :: forall f m a. Monad m => (f ~> m) -> Free f a -> m a
139202
interpret next = go where go = resume pure (\f k -> next f >>= k >>> go)
140203

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.
141207
interpretRec :: forall f m a. MonadRec m => (f ~> m) -> Free f a -> m a
142208
interpretRec nat = tailRecM go <<< view
143209
where
144210
go = runExists case _ of
145211
PureView a -> pure $ Done a
146212
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

Comments
 (0)