Skip to content

Commit 5e4e511

Browse files
committed
add basic cofree implementation
1 parent 9256f60 commit 5e4e511

File tree

4 files changed

+142
-5
lines changed

4 files changed

+142
-5
lines changed

MODULE.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,43 @@
8181
runYoneda :: forall f a b. Yoneda f a -> (a -> b) -> f b
8282

8383

84+
## Module Control.Comonad.Cofree
85+
86+
### Types
87+
88+
data Cofree f a
89+
90+
91+
### Type Class Instances
92+
93+
instance applicativeCofree :: (Applicative f) => Applicative (Cofree f)
94+
95+
instance applyCofree :: (Apply f) => Apply (Cofree f)
96+
97+
instance bindCofree :: (MonadPlus f) => Bind (Cofree f)
98+
99+
instance comonadCofree :: (Functor f) => Comonad (Cofree f)
100+
101+
instance extendCofree :: (Functor f) => Extend (Cofree f)
102+
103+
instance foldableCofree :: (Foldable f) => Foldable (Cofree f)
104+
105+
instance functorCofree :: (Functor f) => Functor (Cofree f)
106+
107+
instance monadCofree :: (MonadPlus f) => Monad (Cofree f)
108+
109+
instance traversableCofree :: (Traversable f) => Traversable (Cofree f)
110+
111+
112+
### Values
113+
114+
head :: forall f a. Cofree f a -> a
115+
116+
mkCofree :: forall f a. a -> f (Cofree f a) -> Cofree f a
117+
118+
tail :: forall f a. Cofree f a -> f (Cofree f a)
119+
120+
84121
## Module Control.Monad.Free
85122

86123
### Types
@@ -150,6 +187,8 @@
150187

151188
delay :: forall a. (Unit -> a) -> Trampoline a
152189

190+
delay' :: forall a. Lazy a -> Trampoline a
191+
153192
done :: forall a. a -> Trampoline a
154193

155194
runTrampoline :: forall a. Trampoline a -> a

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"purescript-either": "*",
1717
"purescript-exists": "*",
1818
"purescript-transformers": "*",
19-
"purescript-lazy": "*"
19+
"purescript-lazy": "*",
20+
"purescript-foldable-traversable": "*"
2021
}
2122
}

src/Control/Comonad/Cofree.purs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module Control.Comonad.Cofree
2+
(
3+
Cofree(),
4+
mkCofree,
5+
head,
6+
tail
7+
) where
8+
9+
import Control.Comonad
10+
import Control.Apply
11+
import Control.Alt
12+
import Control.MonadPlus
13+
import Control.Bind
14+
import Control.Extend
15+
import Control.Monad.Trampoline
16+
import Control.Monad.Free
17+
18+
import Data.Lazy
19+
import Data.Foldable
20+
import Data.Traversable
21+
22+
data Cofree f a = Cofree a (Trampoline (f (Cofree f a)))
23+
24+
mkCofree :: forall f a. a -> (f (Cofree f a)) -> Cofree f a
25+
mkCofree a t = Cofree a (pure t)
26+
27+
head :: forall f a. Cofree f a -> a
28+
head (Cofree h _) = h
29+
30+
tail :: forall f a. Cofree f a -> f (Cofree f a)
31+
tail (Cofree _ t) = runTrampoline t
32+
33+
_tail :: forall f a. Cofree f a -> Trampoline (f (Cofree f a))
34+
_tail (Cofree _ t) = t
35+
36+
_lift :: forall f a b. (Functor f) => (a -> b) -> Trampoline (f a) -> Trampoline (f b)
37+
_lift f = (<$>) $ (<$>) f
38+
39+
instance functorCofree :: (Functor f) => Functor (Cofree f) where
40+
(<$>) f = loop where
41+
loop fa = Cofree (f (head fa)) (_lift loop (_tail fa))
42+
43+
instance foldableCofree :: (Foldable f) => Foldable (Cofree f) where
44+
foldr f = flip go where
45+
go fa b = f a' b' where
46+
a' = head fa
47+
b' = foldr go b (tail fa)
48+
49+
foldl f = go where
50+
go b fa = foldl go b' fa' where
51+
b' = f b (head fa)
52+
fa' = tail fa
53+
54+
foldMap f = go where
55+
go fa = f (head fa) ++ (foldMap go (tail fa))
56+
57+
instance traversableCofree :: (Traversable f) => Traversable (Cofree f) where
58+
traverse f = loop where
59+
loop ta = mkCofree <$> f (head ta) <*> (traverse loop (tail ta))
60+
61+
sequence = traverse id
62+
63+
instance extendCofree :: (Functor f) => Extend (Cofree f) where
64+
(<<=) f = loop where
65+
loop fa = Cofree (f fa) (_lift loop (_tail fa))
66+
67+
instance comonadCofree :: (Functor f) => Comonad (Cofree f) where
68+
extract = head
69+
70+
instance applyCofree :: (Apply f) => Apply (Cofree f) where
71+
(<*>) f x = mkCofree h t where
72+
h = (head f) (head x)
73+
t = (<*>) <$> (tail f) <*> (tail x)
74+
75+
instance applicativeCofree :: (Applicative f) => Applicative (Cofree f) where
76+
pure a = mkCofree a (pure $ pure a)
77+
78+
instance bindCofree :: (MonadPlus f) => Bind (Cofree f) where
79+
(>>=) fa f = loop fa where
80+
loop fa = let fh = f (head fa)
81+
in mkCofree (head fh) ((tail fh) <|> (loop <$> tail fa))
82+
83+
instance monadCofree :: (MonadPlus f) => Monad (Cofree f)

src/Control/Monad/Trampoline.purs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
1-
module Control.Monad.Trampoline where
1+
module Control.Monad.Trampoline
2+
(
3+
Trampoline(),
4+
done,
5+
suspend,
6+
delay',
7+
delay,
8+
runTrampoline
9+
) where
210

311
import Control.Monad.Free
12+
413
import Data.Lazy
14+
import Data.Foldable
15+
import Data.Traversable
516

617
type Trampoline a = Free Lazy a
718

819
done :: forall a. a -> Trampoline a
9-
done = Pure
20+
done = pure
1021

1122
suspend :: forall a. Trampoline a -> Trampoline a
12-
suspend a = Free (defer (const a))
23+
suspend t = Free (defer (const t))
24+
25+
delay' :: forall a. Lazy a -> Trampoline a
26+
delay' a = Free (done <$> a)
1327

1428
delay :: forall a. (Unit -> a) -> Trampoline a
15-
delay a = Free (done <$> defer a)
29+
delay = delay' <<< defer
1630

1731
runTrampoline :: forall a. Trampoline a -> a
1832
runTrampoline = go force

0 commit comments

Comments
 (0)