1
1
-- | This module defines a stack-safe implementation of the _free monad transformer_.
2
2
3
3
module Control.Monad.Free.Trans
4
- ( FreeT ()
4
+ ( FreeT
5
5
, freeT
6
6
, liftFreeT
7
7
, hoistFreeT
@@ -13,13 +13,12 @@ module Control.Monad.Free.Trans
13
13
14
14
import Prelude
15
15
16
- import Data.Exists (Exists (), mkExists , runExists )
17
- import Data.Either (Either (..))
18
16
import Data.Bifunctor (bimap )
17
+ import Data.Either (Either (..))
18
+ import Data.Exists (Exists , mkExists , runExists )
19
19
20
- import Control.Bind ((<=<))
21
- import Control.Monad.Rec.Class (class MonadRec , tailRecM )
22
- import Control.Monad.Trans (class MonadTrans )
20
+ import Control.Monad.Rec.Class (class MonadRec , Step (..), tailRecM )
21
+ import Control.Monad.Trans.Class (class MonadTrans )
23
22
24
23
-- | Instead of implementing `bind` directly, we capture the bind using this data structure, to
25
24
-- | evaluate later.
@@ -40,16 +39,16 @@ freeT = FreeT
40
39
resume :: forall f m a . (Functor f , MonadRec m ) => FreeT f m a -> m (Either a (f (FreeT f m a )))
41
40
resume = tailRecM go
42
41
where
43
- go :: FreeT f m a -> m (Either (FreeT f m a ) (Either a (f (FreeT f m a ))))
44
- go (FreeT f) = map Right (f unit)
42
+ go :: FreeT f m a -> m (Step (FreeT f m a ) (Either a (f (FreeT f m a ))))
43
+ go (FreeT f) = map Done (f unit)
45
44
go (Bind e) = runExists (\(Bound bound f) ->
46
45
case bound unit of
47
46
FreeT m -> do
48
47
e <- m unit
49
48
case e of
50
- Left a -> pure (Left (f a))
51
- Right fc -> pure (Right (Right (map (\h -> h >>= f) fc)))
52
- Bind e1 -> runExists (\(Bound m1 f1) -> pure (Left (bind (m1 unit) (\z -> f1 z >>= f)))) e1) e
49
+ Left a -> pure (Loop (f a))
50
+ Right fc -> pure (Done (Right (map (\h -> h >>= f) fc)))
51
+ Bind e1 -> runExists (\(Bound m1 f1) -> pure (Loop (bind (m1 unit) (\z -> f1 z >>= f)))) e1) e
53
52
54
53
instance functorFreeT :: (Functor f , Functor m ) => Functor (FreeT f m ) where
55
54
map f (FreeT m) = FreeT \_ -> map (bimap f (map (map f))) (m unit)
@@ -73,35 +72,32 @@ instance monadTransFreeT :: (Functor f) => MonadTrans (FreeT f) where
73
72
instance monadRecFreeT :: (Functor f , Monad m ) => MonadRec (FreeT f m ) where
74
73
tailRecM f = go
75
74
where
76
- go s = do
77
- e <- f s
78
- case e of
79
- Left s1 -> go s1
80
- Right a -> pure a
75
+ go s =
76
+ f s >>= case _ of
77
+ Loop s1 -> go s1
78
+ Done a -> pure a
81
79
82
80
-- | Lift an action from the functor `f` to a `FreeT` action.
83
81
liftFreeT :: forall f m a . (Functor f , Monad m ) => f a -> FreeT f m a
84
82
liftFreeT fa = FreeT \_ -> pure (Right (map pure fa))
85
83
86
84
-- | Change the underlying `Monad` for a `FreeT` action.
87
- hoistFreeT :: forall f m n a . (Functor f , Functor n ) => (forall b . m b - > n b ) -> FreeT f m a -> FreeT f n a
85
+ hoistFreeT :: forall f m n a . (Functor f , Functor n ) => (m ~ > n ) -> FreeT f m a -> FreeT f n a
88
86
hoistFreeT = bimapFreeT id
89
87
90
88
-- | Change the base functor `f` for a `FreeT` action.
91
- interpret :: forall f g m a . (Functor f , Functor m ) => (forall b . f b - > g b ) -> FreeT f m a -> FreeT g m a
89
+ interpret :: forall f g m a . (Functor f , Functor m ) => (f ~ > g ) -> FreeT f m a -> FreeT g m a
92
90
interpret nf = bimapFreeT nf id
93
91
94
92
-- | Change the base functor `f` and the underlying `Monad` for a `FreeT` action.
95
- bimapFreeT :: forall f g m n a . (Functor f , Functor n ) => (forall b . f b - > g b ) -> (forall b . m b - > n b ) -> FreeT f m a -> FreeT g n a
93
+ bimapFreeT :: forall f g m n a . (Functor f , Functor n ) => (f ~ > g ) -> (m ~ > n ) -> FreeT f m a -> FreeT g n a
96
94
bimapFreeT nf nm (Bind e) = runExists (\(Bound a f) -> bound (bimapFreeT nf nm <<< a) (bimapFreeT nf nm <<< f)) e
97
95
bimapFreeT nf nm (FreeT m) = FreeT \_ -> map (nf <<< map (bimapFreeT nf nm)) <$> nm (m unit)
98
96
99
97
-- | Run a `FreeT` computation to completion.
100
98
runFreeT :: forall f m a . (Functor f , MonadRec m ) => (f (FreeT f m a ) -> m (FreeT f m a )) -> FreeT f m a -> m a
101
99
runFreeT interp = tailRecM (go <=< resume)
102
100
where
103
- go :: Either a (f (FreeT f m a )) -> m (Either (FreeT f m a ) a )
104
- go (Left a) = pure (Right a)
105
- go (Right fc) = do
106
- c <- interp fc
107
- pure (Left c)
101
+ go :: Either a (f (FreeT f m a )) -> m (Step (FreeT f m a ) a )
102
+ go (Left a) = pure (Done a)
103
+ go (Right fc) = Loop <$> interp fc
0 commit comments