Skip to content

Commit ec4716a

Browse files
committed
Update FFI code for Free, fixes #7
1 parent e5c7a9b commit ec4716a

File tree

2 files changed

+87
-63
lines changed

2 files changed

+87
-63
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,6 @@
182182

183183
pureF :: forall f a. (Applicative f) => a -> Free f a
184184

185-
resume :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) a
186-
187-
resumeGosub :: forall f a. (Functor f) => (forall s. (forall r. (Unit -> Free f r) -> (r -> Free f a) -> s) -> s) -> Either (f (Free f a)) (Free f a)
188-
189185

190186
## Module Control.Monad.Identity
191187

src/Control/Monad/Free.purs

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
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
211

312
import Control.Monad.Trans
413
import Control.Monad.Eff
514
import Data.Either
15+
import Data.Function
616

717
data Free f a = Pure a
818
| Free (f (Free f a))
@@ -53,69 +63,87 @@ goM k f = case resume f of
5363
Left s -> k s >>= goM k
5464
Right a -> return a
5565

56-
resumeGosub :: forall f a. (Functor f) => (forall s. (forall r. (Unit -> Free f r) -> (r -> Free f a) -> s) -> s) -> Either (f (Free f a)) (Free f a)
57-
resumeGosub f = f (\a g ->
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 ->
5868
case a unit of
5969
Pure a -> Right (g a)
6070
Free t -> Left ((\h -> h >>= g) <$> t)
6171
Gosub h -> Right (h (\b i -> b unit >>= (\x -> i x >>= g)))
6272
)
6373

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-
\ }\
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)) {\
133+
\ var x = fromRight(r);\
134+
\ return function() { return x; };\
81135
\ }\
136+
\ value = fn(fromLeft(r))();\
137+
\ }\
82138
\ };\
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
139+
\}" :: forall e f a. Fn6
140+
(Free f a -> Either (f (Free f a)) a)
141+
(Either (f (Free f a)) a -> Boolean)
142+
(Either (f (Free f a)) a -> (f (Free f a)))
143+
(Either (f (Free f a)) a -> a)
144+
(f (Free f a) -> Eff e (Free f a))
145+
(Free f a)
146+
(Eff e a)
147+
148+
goEff :: forall e f a. (Functor f) => (f (Free f a) -> Eff e (Free f a)) -> Free f a -> Eff e a
149+
goEff fn f = runFn6 goEffImpl resume isRight unsafeLeft unsafeRight fn f

0 commit comments

Comments
 (0)