Skip to content

Commit 3b28cbc

Browse files
committed
Merge branch 'puffnfresh-trampoline'
2 parents a567371 + dd131c0 commit 3b28cbc

File tree

4 files changed

+171
-10
lines changed

4 files changed

+171
-10
lines changed

README.md

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,81 @@
1-
# purescript-free
1+
# Module Documentation
22

3-
Free monads based on the Haskell [implementation](https://github.com/ekmett/free).
3+
## Module Control.Monad.Free
4+
5+
### Types
6+
7+
data Free f a where
8+
Return :: a -> Free f a
9+
Suspend :: f (Free f a) -> Free f a
10+
Gosub :: forall s. (forall r. ({} -> Free f r) -> (r -> Free f a) -> s) -> s -> Free f a
11+
12+
13+
### Type Classes
14+
15+
class MonadFree f m where
16+
wrap :: forall a. f (m a) -> m a
17+
18+
19+
### Type Class Instances
20+
21+
instance applicativeFree :: (Functor f) => Applicative (Free f)
22+
23+
instance applyFree :: (Functor f) => Apply (Free f)
24+
25+
instance bindFree :: (Functor f) => Bind (Free f)
26+
27+
instance functorFree :: (Functor f) => Functor (Free f)
28+
29+
instance monadFree :: (Functor f) => Monad (Free f)
30+
31+
instance monadTransFree :: MonadTrans Free
32+
33+
instance monadFreeFree :: (Functor f) => MonadFree f (Free f)
34+
35+
36+
### Values
37+
38+
bindFree :: forall f a b. (a -> Free f b) -> Free f a -> Free f b
39+
40+
go :: forall f a. (Functor f) => (f (Free f a) -> Free f a) -> Free f a -> a
41+
42+
liftF :: forall f a. (Functor f) => f a -> Free f a
43+
44+
pureF :: forall f a. (Applicative f) => a -> Free f a
45+
46+
-- Note: can blow the stack!
47+
iterM :: forall f m a. (Functor f, Monad m) => (f (m a) -> m a) -> Free f a -> m a
48+
49+
resume :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) a
50+
51+
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)
52+
53+
54+
## Module Control.Monad.Trampoline
55+
56+
### Types
57+
58+
data Delay a where
59+
Delay :: { } -> a -> Delay a
60+
61+
type Trampoline a = Free Delay a
62+
63+
64+
### Type Class Instances
65+
66+
instance delayApplicative :: Applicative Delay
67+
68+
instance delayApply :: Apply Delay
69+
70+
instance delayFunctor :: Functor Delay
71+
72+
73+
### Values
74+
75+
delay :: forall a. ({ } -> a) -> Trampoline a
76+
77+
done :: forall a. a -> Trampoline a
78+
79+
runTrampoline :: forall a. Trampoline a -> a
80+
81+
suspend :: forall a. Trampoline a -> Trampoline a

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"dist"
1616
],
1717
"dependencies": {
18-
"purescript-transformers": "64fa7200dc328fc79090426cddb64ed6e4ccffc9"
18+
"purescript-transformers": "64fa7200dc328fc79090426cddb64ed6e4ccffc9",
19+
"purescript-either": "*"
1920
}
2021
}

src/Control/Monad/Free.purs

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
module Control.Monad.Free where
22

33
import Prelude
4+
import Data.Either
45
import Control.Monad.Trans
56

6-
data Free f a = Pure a | Free (f (Free f a))
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)
710

811
class MonadFree f m where
912
wrap :: forall a. f (m a) -> m a
1013

1114
instance functorFree :: (Functor f) => Functor (Free f) where
12-
(<$>) f = go where
13-
go (Pure a) = Pure (f a)
14-
go (Free fa) = Free (go <$> fa)
15+
(<$>) f (Pure a) = Pure (f a)
16+
(<$>) f g = liftA1 f g
1517

1618
instance applyFree :: (Functor f) => Apply (Free f) where
1719
(<*>) = ap
@@ -20,8 +22,8 @@ instance applicativeFree :: (Functor f) => Applicative (Free f) where
2022
pure = Pure
2123

2224
instance bindFree :: (Functor f) => Bind (Free f) where
23-
(>>=) (Pure a) f = f a
24-
(>>=) (Free m) f = Free ((<$>) (\a -> a >>= f) m)
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)
2527

2628
instance monadFree :: (Functor f) => Monad (Free f)
2729

@@ -36,6 +38,58 @@ instance monadFreeFree :: (Functor f) => MonadFree f (Free f) where
3638
liftF :: forall f m a. (Functor f, Monad m, MonadFree f m) => f a -> m a
3739
liftF fa = wrap $ return <$> fa
3840

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!
3945
iterM :: forall f m a. (Functor f, Monad m) => (f (m a) -> m a) -> Free f a -> m a
4046
iterM _ (Pure a) = return a
41-
iterM k (Free f) = k $ (iterM k) <$> f
47+
iterM k (Free f) = k $ iterM k <$> f
48+
iterM k (Gosub f) = iterM k $ f (\req recv -> req {} >>= recv)
49+
50+
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)
51+
resumeGosub f = f (\a g ->
52+
case a {} of
53+
Pure a -> Right (g a)
54+
Free t -> Left ((\h -> h >>= g) <$> t)
55+
Gosub h -> Right (h (\b i -> b {} >>= (\x -> i x >>= g)))
56+
)
57+
58+
foreign import resume
59+
"function resume(__dict_Functor) {\
60+
\ return function(__copy__1) {\
61+
\ var _1 = __copy__1;\
62+
\ tco: while (true)\
63+
\ if (_1.ctor === 'Control.Monad.Free.Pure')\
64+
\ return Data_Either.Right(_1.values[0]);\
65+
\ else if (_1.ctor === 'Control.Monad.Free.Free')\
66+
\ return Data_Either.Left(_1.values[0]);\
67+
\ else {\
68+
\ var x = resumeGosub(__dict_Functor)(_1.values[0]);\
69+
\ if (x.ctor === 'Data.Either.Left')\
70+
\ return x;\
71+
\ else {\
72+
\ _1 = x.values[0];\
73+
\ continue tco;\
74+
\ }\
75+
\ }\
76+
\ };\
77+
\}" :: forall f a. (Functor f) => Free f a -> Either (f (Free f a)) a
78+
79+
foreign import go
80+
"function go(__dict_Functor) {\
81+
\ return function(f) {\
82+
\ return function(__copy__1) {\
83+
\ var _1 = __copy__1;\
84+
\ var r;\
85+
\ tco: while (true) {\
86+
\ r = resume(__dict_Functor)(_1);\
87+
\ if (r.ctor === 'Data.Either.Left') {\
88+
\ _1 = f(r.values[0]);\
89+
\ continue tco;\
90+
\ } else\
91+
\ return r.values[0];\
92+
\ }\
93+
\ };\
94+
\ };\
95+
\}" :: forall f a. (Functor f) => (f (Free f a) -> Free f a) -> Free f a -> a

src/Control/Monad/Trampoline.purs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module Control.Monad.Trampoline where
2+
3+
import Control.Monad.Free
4+
5+
data Delay a = Delay ({} -> a)
6+
7+
instance delayFunctor :: Functor Delay where
8+
(<$>) f (Delay g) = Delay (const (f (g {})))
9+
10+
instance delayApply :: Apply Delay where
11+
(<*>) (Delay f) (Delay a) = Delay (\{} -> (f {}) (a {}))
12+
13+
instance delayApplicative :: Applicative Delay where
14+
pure a = Delay (\{} -> a)
15+
16+
type Trampoline a = Free Delay a
17+
18+
done :: forall a. a -> Trampoline a
19+
done = Pure
20+
21+
suspend :: forall a. Trampoline a -> Trampoline a
22+
suspend a = Free (Delay (\{} -> a))
23+
24+
delay :: forall a. ({} -> a) -> Trampoline a
25+
delay a = Free (done <$> Delay a)
26+
27+
runTrampoline :: forall a. Trampoline a -> a
28+
runTrampoline = go (\(Delay f) -> f {})

0 commit comments

Comments
 (0)