|
1 |
| -module Control.Monad.Free where |
| 1 | +module Control.Monad.Free |
| 2 | + ( Free(..) |
| 3 | + , MonadFree, wrap |
| 4 | + , liftF |
| 5 | + , pureF |
| 6 | + , iterM |
| 7 | + , goM |
| 8 | + , go |
| 9 | + , goEff |
| 10 | + ) where |
2 | 11 |
|
3 | 12 | import Control.Monad.Trans
|
4 | 13 | import Control.Monad.Eff
|
5 | 14 | import Data.Either
|
| 15 | +import Data.Function |
6 | 16 |
|
7 | 17 | data Free f a = Pure a
|
8 | 18 | | Free (f (Free f a))
|
9 |
| - | Gosub (forall s. (forall r. ({} -> Free f r) -> (r -> Free f a) -> s) -> s) |
| 19 | + | Gosub (forall s. (forall r. (Unit -> Free f r) -> (r -> Free f a) -> s) -> s) |
10 | 20 |
|
11 | 21 | class MonadFree f m where
|
12 | 22 | wrap :: forall a. f (m a) -> m a
|
@@ -45,77 +55,92 @@ pureF a = Free (pure (Pure a))
|
45 | 55 | iterM :: forall f m a. (Functor f, Monad m) => (forall a. f (m a) -> m a) -> Free f a -> m a
|
46 | 56 | iterM _ (Pure a) = return a
|
47 | 57 | iterM k (Free f) = k $ iterM k <$> f
|
48 |
| -iterM k (Gosub f) = f (\req recv -> iterM k (req {}) >>= (iterM k <<< recv)) |
| 58 | +iterM k (Gosub f) = f (\req recv -> iterM k (req unit) >>= (iterM k <<< recv)) |
49 | 59 |
|
50 | 60 | -- Note: can blow the stack!
|
51 | 61 | goM :: forall f m a. (Functor f, Monad m) => (f (Free f a) -> m (Free f a)) -> Free f a -> m a
|
52 | 62 | goM k f = case resume f of
|
53 | 63 | Left s -> k s >>= goM k
|
54 | 64 | Right a -> return a
|
55 | 65 |
|
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 |
| 66 | +resumeGosub :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) (Free f a) |
| 67 | +resumeGosub (Gosub f) = f (\a g -> |
| 68 | + case a unit of |
59 | 69 | Pure a -> Right (g a)
|
60 | 70 | Free t -> Left ((\h -> h >>= g) <$> t)
|
61 |
| - Gosub h -> Right (h (\b i -> b {} >>= (\x -> i x >>= g))) |
| 71 | + Gosub h -> Right (h (\b i -> b unit >>= (\x -> i x >>= g))) |
62 | 72 | )
|
63 | 73 |
|
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 |
| - \ }\ |
| 74 | +isGosub :: forall f a. Free f a -> Boolean |
| 75 | +isGosub (Gosub _) = true |
| 76 | +isGosub _ = false |
| 77 | + |
| 78 | +unsafeFreeToEither :: forall f a. Free f a -> Either (f (Free f a)) a |
| 79 | +unsafeFreeToEither (Pure x) = Right x |
| 80 | +unsafeFreeToEither (Free x) = Left x |
| 81 | + |
| 82 | +unsafeLeft :: forall a b. Either a b -> a |
| 83 | +unsafeLeft (Left x) = x |
| 84 | + |
| 85 | +unsafeRight :: forall a b. Either a b -> b |
| 86 | +unsafeRight (Right x) = x |
| 87 | + |
| 88 | +foreign import resumeImpl |
| 89 | + "function resumeImpl(isGosub, isLeft, toEither, fromRight, resumeGosub, value) {\ |
| 90 | + \ while (true) {\ |
| 91 | + \ if (!isGosub(value)) return toEither(value);\ |
| 92 | + \ var x = resumeGosub(value);\ |
| 93 | + \ if (isLeft(x)) return x;\ |
| 94 | + \ else value = fromRight(x);\ |
| 95 | + \ }\ |
| 96 | + \}" :: forall f a. Fn6 |
| 97 | + (Free f a -> Boolean) |
| 98 | + (Either (f (Free f a)) a -> Boolean) |
| 99 | + (Free f a -> Either (f (Free f a)) a) |
| 100 | + (Either (f (Free f a)) a -> a) |
| 101 | + (Free f a -> Either (f (Free f a)) (Free f a)) |
| 102 | + (Free f a) |
| 103 | + (Either (f (Free f a)) a) |
| 104 | + |
| 105 | +resume :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) a |
| 106 | +resume f = runFn6 resumeImpl isGosub isLeft unsafeFreeToEither unsafeRight resumeGosub f |
| 107 | + |
| 108 | +foreign import goImpl |
| 109 | + "function goImpl(resume, isRight, fromLeft, fromRight, fn, value) {\ |
| 110 | + \ while (true) {\ |
| 111 | + \ var r = resume(value);\ |
| 112 | + \ if (isRight(r)) return fromRight(r);\ |
| 113 | + \ value = fn(fromLeft(r));\ |
| 114 | + \ }\ |
| 115 | + \}" :: forall f a. Fn6 |
| 116 | + (Free f a -> Either (f (Free f a)) a) |
| 117 | + (Either (f (Free f a)) a -> Boolean) |
| 118 | + (Either (f (Free f a)) a -> (f (Free f a))) |
| 119 | + (Either (f (Free f a)) a -> a) |
| 120 | + (f (Free f a) -> Free f a) |
| 121 | + (Free f a) |
| 122 | + a |
| 123 | + |
| 124 | +go :: forall f a. (Functor f) => (f (Free f a) -> Free f a) -> Free f a -> a |
| 125 | +go fn f = runFn6 goImpl resume isRight unsafeLeft unsafeRight fn f |
| 126 | + |
| 127 | +foreign import goEffImpl |
| 128 | + "function goEffImpl(resume, isRight, fromLeft, fromRight, fn, value) {\ |
| 129 | + \ return function(){\ |
| 130 | + \ while (true) {\ |
| 131 | + \ var r = resume(value);\ |
| 132 | + \ if (isRight(r)) return fromRight(r);\ |
| 133 | + \ value = fn(fromLeft(r))();\ |
| 134 | + \ }\ |
82 | 135 | \ };\
|
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 |
| 136 | + \}" :: forall e f a. Fn6 |
| 137 | + (Free f a -> Either (f (Free f a)) a) |
| 138 | + (Either (f (Free f a)) a -> Boolean) |
| 139 | + (Either (f (Free f a)) a -> (f (Free f a))) |
| 140 | + (Either (f (Free f a)) a -> a) |
| 141 | + (f (Free f a) -> Eff e (Free f a)) |
| 142 | + (Free f a) |
| 143 | + (Eff e a) |
| 144 | + |
| 145 | +goEff :: forall e f a. (Functor f) => (f (Free f a) -> Eff e (Free f a)) -> Free f a -> Eff e a |
| 146 | +goEff fn f = runFn6 goEffImpl resume isRight unsafeLeft unsafeRight fn f |
0 commit comments