|
| 1 | +module Control.Monad.Free where |
| 2 | + |
| 3 | +import Control.Monad.Trans |
| 4 | +import Control.Monad.Eff |
| 5 | +import Data.Either |
| 6 | + |
| 7 | +data Free f a = Pure a |
| 8 | + | Free (f (Free f a)) |
| 9 | + | Gosub (forall s. (forall r. ({} -> Free f r) -> (r -> Free f a) -> s) -> s) |
| 10 | + |
| 11 | +class MonadFree f m where |
| 12 | + wrap :: forall a. f (m a) -> m a |
| 13 | + |
| 14 | +instance functorFree :: (Functor f) => Functor (Free f) where |
| 15 | + (<$>) f (Pure a) = Pure (f a) |
| 16 | + (<$>) f g = liftA1 f g |
| 17 | + |
| 18 | +instance applyFree :: (Functor f) => Apply (Free f) where |
| 19 | + (<*>) = ap |
| 20 | + |
| 21 | +instance applicativeFree :: (Functor f) => Applicative (Free f) where |
| 22 | + pure = Pure |
| 23 | + |
| 24 | +instance bindFree :: (Functor f) => Bind (Free f) where |
| 25 | + (>>=) (Gosub g) f = Gosub (\h -> g (\a i -> h a (\x -> Gosub (\j -> j (const (i x)) f)))) |
| 26 | + (>>=) a f = Gosub (\h -> h (const a) f) |
| 27 | + |
| 28 | +instance monadFree :: (Functor f) => Monad (Free f) |
| 29 | + |
| 30 | +instance monadTransFree :: MonadTrans Free where |
| 31 | + lift f = Free $ do |
| 32 | + a <- f |
| 33 | + return (Pure a) |
| 34 | + |
| 35 | +instance monadFreeFree :: (Functor f) => MonadFree f (Free f) where |
| 36 | + wrap = Free |
| 37 | + |
| 38 | +liftF :: forall f m a. (Functor f, Monad m, MonadFree f m) => f a -> m a |
| 39 | +liftF fa = wrap $ return <$> fa |
| 40 | + |
| 41 | +pureF :: forall f a. (Applicative f) => a -> Free f a |
| 42 | +pureF a = Free (pure (Pure a)) |
| 43 | + |
| 44 | +-- Note: can blow the stack! |
| 45 | +iterM :: forall f m a. (Functor f, Monad m) => (forall a. f (m a) -> m a) -> Free f a -> m a |
| 46 | +iterM _ (Pure a) = return a |
| 47 | +iterM k (Free f) = k $ iterM k <$> f |
| 48 | +iterM k (Gosub f) = f (\req recv -> iterM k (req {}) >>= (iterM k <<< recv)) |
| 49 | + |
| 50 | +-- Note: can blow the stack! |
| 51 | +goM :: forall f m a. (Functor f, Monad m) => (f (Free f a) -> m (Free f a)) -> Free f a -> m a |
| 52 | +goM k f = case resume f of |
| 53 | + Left s -> k s >>= goM k |
| 54 | + Right a -> return a |
| 55 | + |
| 56 | +resumeGosub :: forall f a. (Functor f) => (forall s. (forall r. ({} -> Free f r) -> (r -> Free f a) -> s) -> s) -> Either (f (Free f a)) (Free f a) |
| 57 | +resumeGosub f = f (\a g -> |
| 58 | + case a {} of |
| 59 | + Pure a -> Right (g a) |
| 60 | + Free t -> Left ((\h -> h >>= g) <$> t) |
| 61 | + Gosub h -> Right (h (\b i -> b {} >>= (\x -> i x >>= g))) |
| 62 | + ) |
| 63 | + |
| 64 | +foreign import resume |
| 65 | + "function resume(__dict_Functor) {\ |
| 66 | + \ return function(__copy__1) {\ |
| 67 | + \ var _1 = __copy__1;\ |
| 68 | + \ tco: while (true)\ |
| 69 | + \ if (_1.ctor === 'Control.Monad.Free.Pure')\ |
| 70 | + \ return Data_Either.Right(_1.values[0]);\ |
| 71 | + \ else if (_1.ctor === 'Control.Monad.Free.Free')\ |
| 72 | + \ return Data_Either.Left(_1.values[0]);\ |
| 73 | + \ else {\ |
| 74 | + \ var x = resumeGosub(__dict_Functor)(_1.values[0]);\ |
| 75 | + \ if (x.ctor === 'Data.Either.Left')\ |
| 76 | + \ return x;\ |
| 77 | + \ else {\ |
| 78 | + \ _1 = x.values[0];\ |
| 79 | + \ continue tco;\ |
| 80 | + \ }\ |
| 81 | + \ }\ |
| 82 | + \ };\ |
| 83 | + \}" :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) a |
| 84 | + |
| 85 | +foreign import go |
| 86 | + "function go(__dict_Functor) {\ |
| 87 | + \ return function(f) {\ |
| 88 | + \ return function(__copy__1) {\ |
| 89 | + \ var _1 = __copy__1;\ |
| 90 | + \ var r;\ |
| 91 | + \ tco: while (true) {\ |
| 92 | + \ r = resume(__dict_Functor)(_1);\ |
| 93 | + \ if (r.ctor === 'Data.Either.Left') {\ |
| 94 | + \ _1 = f(r.values[0]);\ |
| 95 | + \ continue tco;\ |
| 96 | + \ } else\ |
| 97 | + \ return r.values[0];\ |
| 98 | + \ }\ |
| 99 | + \ };\ |
| 100 | + \ };\ |
| 101 | + \}" :: forall f a. (Functor f) => (f (Free f a) -> Free f a) -> Free f a -> a |
| 102 | + |
| 103 | +foreign import goEff |
| 104 | + "function goEff(__dict_Functor) {\ |
| 105 | + \ return function(f) {\ |
| 106 | + \ return function(__copy__1) {\ |
| 107 | + \ return function(){\ |
| 108 | + \ var _1 = __copy__1;\ |
| 109 | + \ var r;\ |
| 110 | + \ tco: while (true) {\ |
| 111 | + \ r = resume(__dict_Functor)(_1);\ |
| 112 | + \ if (r.ctor === 'Data.Either.Left') {\ |
| 113 | + \ _1 = f(r.values[0])();\ |
| 114 | + \ continue tco;\ |
| 115 | + \ } else\ |
| 116 | + \ return function(){return r.values[0];};\ |
| 117 | + \ }\ |
| 118 | + \ };\ |
| 119 | + \ };\ |
| 120 | + \ };\ |
| 121 | + \}" :: forall e f a. (Functor f) => (f (Free f a) -> Eff e (Free f a)) -> Free f a -> Eff e a |
0 commit comments