@@ -81,6 +81,12 @@ resumeGosub (Gosub f) = f (\a g ->
81
81
Gosub h -> Right (h (\b i -> b unit >>= (\x -> i x >>= g)))
82
82
)
83
83
84
+ unsafeLeft :: forall a b . Either a b -> a
85
+ unsafeLeft (Left x) = x
86
+
87
+ unsafeRight :: forall a b . Either a b -> b
88
+ unsafeRight (Right x) = x
89
+
84
90
resume :: forall f a . (Functor f ) => Free f a -> Either (f (Free f a )) a
85
91
resume f = case f of
86
92
Pure x -> Right x
@@ -94,10 +100,26 @@ go fn f = case resume f of
94
100
Left l -> go fn (fn l)
95
101
Right r -> r
96
102
103
+ foreign import goEffImpl
104
+ " function goEffImpl(resume, isRight, fromLeft, fromRight, fn, value) {\
105
+ \ return function(){\
106
+ \ while (true) {\
107
+ \ var r = resume(value);\
108
+ \ if (isRight(r)) return fromRight(r);\
109
+ \ value = fn(fromLeft(r))();\
110
+ \ }\
111
+ \ };\
112
+ \}" :: forall e f a . Fn6
113
+ (Free f a -> Either (f (Free f a )) a )
114
+ (Either (f (Free f a )) a -> Boolean )
115
+ (Either (f (Free f a )) a -> (f (Free f a )))
116
+ (Either (f (Free f a )) a -> a )
117
+ (f (Free f a ) -> Eff e (Free f a ))
118
+ (Free f a )
119
+ (Eff e a )
120
+
97
121
goEff :: forall e f a . (Functor f ) => (f (Free f a ) -> Eff e (Free f a )) -> Free f a -> Eff e a
98
- goEff fn f = case resume f of
99
- Left l -> fn l >>= goEff fn
100
- Right r -> return r
122
+ goEff fn f = runFn6 goEffImpl resume isRight unsafeLeft unsafeRight fn f
101
123
102
124
-- Note: can blow the stack!
103
125
goMC :: forall f m a . (Monad m ) => Natural f m -> FreeC f a -> m a
0 commit comments