@@ -5,14 +5,17 @@ module Control.Monad.Free
5
5
, liftF , liftFC
6
6
, pureF , pureFC
7
7
, mapF , injC
8
- , iterM
9
- , goM , goMC
10
- , go
11
- , goEff , goEffC
8
+ , runFree
9
+ , runFreeM
10
+ , runFreeC
11
+ , runFreeCM
12
12
) where
13
13
14
14
import Control.Monad.Trans
15
15
import Control.Monad.Eff
16
+ import Control.Monad.Rec.Class
17
+
18
+ import Data.Identity
16
19
import Data.Coyoneda
17
20
import Data.Either
18
21
import Data.Function
@@ -69,69 +72,42 @@ mapF t fa = either (\s -> Free <<< t $ mapF t <$> s) Pure (resume fa)
69
72
injC :: forall f g a . (Inject f g ) => FreeC f a -> FreeC g a
70
73
injC = mapF (liftCoyonedaT inj)
71
74
72
- -- Note: can blow the stack!
73
- iterM :: forall f m a . (Functor f , Monad m ) => (forall a . f (m a ) -> m a ) -> Free f a -> m a
74
- iterM _ (Pure a) = return a
75
- iterM k (Free f) = k $ iterM k <$> f
76
- iterM k (Gosub f) = f (\req recv -> iterM k (req unit) >>= (iterM k <<< recv))
77
-
78
- -- Note: can blow the stack!
79
- goM :: forall f m a . (Functor f , Monad m ) => (f (Free f a ) -> m (Free f a )) -> Free f a -> m a
80
- goM k f = case resume f of
81
- Left s -> k s >>= goM k
82
- Right a -> return a
83
-
84
- resumeGosub :: forall f a . (Functor f ) => Free f a -> Either (f (Free f a )) (Free f a )
85
- resumeGosub (Gosub f) = f (\a g ->
86
- case a unit of
87
- Pure a -> Right (g a)
88
- Free t -> Left ((\h -> h >>= g) <$> t)
89
- Gosub h -> Right (h (\b i -> b unit >>= (\x -> i x >>= g)))
90
- )
91
-
92
- unsafeLeft :: forall a b . Either a b -> a
93
- unsafeLeft (Left x) = x
94
-
95
- unsafeRight :: forall a b . Either a b -> b
96
- unsafeRight (Right x) = x
97
-
98
75
resume :: forall f a . (Functor f ) => Free f a -> Either (f (Free f a )) a
99
76
resume f = case f of
100
77
Pure x -> Right x
101
78
Free x -> Left x
102
79
g -> case resumeGosub g of
103
80
Left l -> Left l
104
81
Right r -> resume r
82
+ where
83
+ resumeGosub :: Free f a -> Either (f (Free f a )) (Free f a )
84
+ resumeGosub (Gosub f) = f (\a g ->
85
+ case a unit of
86
+ Pure a -> Right (g a)
87
+ Free t -> Left ((\h -> h >>= g) <$> t)
88
+ Gosub h -> Right (h (\b i -> b unit >>= (\x -> i x >>= g)))
89
+ )
90
+
91
+ -- | `runFree` runs a computation of type `Free f a`, using a function which unwraps a single layer of
92
+ -- | the functor `f` at a time.
93
+ runFree :: forall f a . (Functor f ) => (f (Free f a ) -> Free f a ) -> Free f a -> a
94
+ runFree fn = runIdentity <<< runFreeM (Identity <<< fn)
95
+
96
+ -- | `runFreeM` runs a compuation of type `Free f a` in any `Monad` which supports tail recursion.
97
+ -- | See the `MonadRec` type class for more details.
98
+ runFreeM :: forall f m a . (Functor f , MonadRec m ) => (f (Free f a ) -> m (Free f a )) -> Free f a -> m a
99
+ runFreeM fn = tailRecM \f ->
100
+ case resume f of
101
+ Left fs -> Left <$> fn fs
102
+ Right a -> return (Right a)
103
+
104
+ -- | `runFreeC` is the equivalent of `runFree` for type constructors transformed with `Coyoneda`,
105
+ -- | hence we have no requirement that `f` be a `Functor`.
106
+ runFreeC :: forall f a . (forall a . f a -> a ) -> FreeC f a -> a
107
+ runFreeC nat = runIdentity <<< runFreeCM (Identity <<< nat)
108
+
109
+ -- | `runFreeCM` is the equivalent of `runFreeM` for type constructors transformed with `Coyoneda`,
110
+ -- | hence we have no requirement that `f` be a `Functor`.
111
+ runFreeCM :: forall f m a . (MonadRec m ) => Natural f m -> FreeC f a -> m a
112
+ runFreeCM nat = runFreeM (liftCoyonedaTF nat)
105
113
106
- go :: forall f a . (Functor f ) => (f (Free f a ) -> Free f a ) -> Free f a -> a
107
- go fn f = case resume f of
108
- Left l -> go fn (fn l)
109
- Right r -> r
110
-
111
- foreign import goEffImpl " " "
112
- function goEffImpl(resume, isRight, fromLeft, fromRight, fn, value) {
113
- return function(){
114
- while (true) {
115
- var r = resume(value);
116
- if (isRight(r)) return fromRight(r);
117
- value = fn(fromLeft(r))();
118
- }
119
- };
120
- }" " " :: forall e f a . Fn6
121
- (Free f a -> Either (f (Free f a )) a )
122
- (Either (f (Free f a )) a -> Boolean )
123
- (Either (f (Free f a )) a -> (f (Free f a )))
124
- (Either (f (Free f a )) a -> a )
125
- (f (Free f a ) -> Eff e (Free f a ))
126
- (Free f a )
127
- (Eff e a )
128
-
129
- goEff :: forall e f a . (Functor f ) => (f (Free f a ) -> Eff e (Free f a )) -> Free f a -> Eff e a
130
- goEff fn f = runFn6 goEffImpl resume isRight unsafeLeft unsafeRight fn f
131
-
132
- -- Note: can blow the stack!
133
- goMC :: forall f m a . (Monad m ) => Natural f m -> FreeC f a -> m a
134
- goMC nat = goM (liftCoyonedaTF nat)
135
-
136
- goEffC :: forall e f a . Natural f (Eff e ) -> FreeC f a -> Eff e a
137
- goEffC nat = goEff (liftCoyonedaTF nat)
0 commit comments