Skip to content

Commit 15dea96

Browse files
committed
Add Costar, more Star instances (#16)
1 parent a649126 commit 15dea96

File tree

3 files changed

+132
-2
lines changed

3 files changed

+132
-2
lines changed

bower.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"package.json"
2323
],
2424
"dependencies": {
25+
"purescript-distributive": "^1.0.0-rc.1",
2526
"purescript-either": "^1.0.0-rc.1",
2627
"purescript-tuples": "^1.0.0-rc.1"
2728
}

src/Data/Profunctor/Costar.purs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module Data.Profunctor.Costar where
2+
3+
import Prelude
4+
5+
import Control.Comonad (class Comonad, extract)
6+
import Control.Extend (class Extend, (=<=))
7+
8+
import Data.Distributive (class Distributive, distribute)
9+
import Data.Either (Either(..), either)
10+
import Data.Functor.Invariant (class Invariant, imapF)
11+
import Data.Profunctor (class Profunctor)
12+
import Data.Profunctor.Closed (class Closed)
13+
import Data.Profunctor.Cochoice (class Cochoice)
14+
import Data.Profunctor.Costrong (class Costrong)
15+
import Data.Profunctor.Strong (class Strong)
16+
import Data.Tuple (Tuple(..), fst, snd)
17+
18+
-- | `Costar` turns a `Functor` into a `Profunctor` "backwards".
19+
-- |
20+
-- | `Costar f` is also the co-Kleisli category for `f`.
21+
newtype Costar f b a = Costar (f b -> a)
22+
23+
-- | Unwrap a value of type `Costar f a b`.
24+
unCostar :: forall f a b. Costar f b a -> f b -> a
25+
unCostar (Costar f) = f
26+
27+
instance semigroupoidCostar :: Extend f => Semigroupoid (Costar f) where
28+
compose (Costar f) (Costar g) = Costar (f =<= g)
29+
30+
instance categoryCostar :: Comonad f => Category (Costar f) where
31+
id = Costar extract
32+
33+
instance functorCostar :: Functor (Costar f a) where
34+
map f (Costar g) = Costar (f <<< g)
35+
36+
instance invariantCostar :: Invariant (Costar f a) where
37+
imap = imapF
38+
39+
instance applyCostar :: Apply (Costar f a) where
40+
apply (Costar f) (Costar g) = Costar \a -> f a (g a)
41+
42+
instance applicativeCostar :: Applicative (Costar f a) where
43+
pure a = Costar \_ -> a
44+
45+
instance bindCostar :: Bind (Costar f a) where
46+
bind (Costar m) f = Costar \x -> unCostar (f (m x)) x
47+
48+
instance monadCostar :: Monad (Costar f a)
49+
50+
instance distributiveCostar :: Distributive f => Distributive (Costar f a) where
51+
distribute f = Costar \g -> map ((_ $ g) <<< unCostar) f
52+
collect f = distribute <<< map f
53+
54+
instance profunctorCostar :: Functor f => Profunctor (Costar f) where
55+
dimap f g (Costar h) = Costar (map f >>> h >>> g)
56+
57+
instance strongCostar :: Comonad f => Strong (Costar f) where
58+
first (Costar f) = Costar \x -> Tuple (f (map fst x)) (snd (extract x))
59+
second (Costar f) = Costar \x -> Tuple (fst (extract x)) (f (map snd x))
60+
61+
instance costrongCostar :: Functor f => Costrong (Costar f) where
62+
unfirst (Costar f) = Costar \fb ->
63+
let bd = f ((\a -> Tuple a (snd bd)) <$> fb) in fst bd
64+
unsecond (Costar f) = Costar \fb ->
65+
let db = f ((\a -> Tuple (fst db) a) <$> fb) in snd db
66+
67+
instance cochoiceCostar :: Applicative f => Cochoice (Costar f) where
68+
unleft (Costar f) =
69+
let g = either id (\r -> g (pure (Right r))) <<< f
70+
in Costar (g <<< map Left)
71+
unright (Costar f) =
72+
let g = either (\l -> g (pure (Left l))) id <<< f
73+
in Costar (g <<< map Right)
74+
75+
instance closedCostar :: Functor f => Closed (Costar f) where
76+
closed (Costar f) = Costar \g x -> f (map (_ $ x) g)

src/Data/Profunctor/Star.purs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,69 @@ module Data.Profunctor.Star where
22

33
import Prelude
44

5-
import Data.Tuple (Tuple(..))
5+
import Control.Alt (class Alt, (<|>))
6+
import Control.Alternative (class Alternative)
7+
import Control.MonadPlus (class MonadPlus)
8+
import Control.MonadZero (class MonadZero)
9+
import Control.Plus (class Plus, empty)
10+
11+
import Data.Distributive (class Distributive, distribute, collect)
612
import Data.Either (Either(..), either)
13+
import Data.Functor.Invariant (class Invariant, imap)
714
import Data.Profunctor (class Profunctor)
8-
import Data.Profunctor.Strong (class Strong)
915
import Data.Profunctor.Choice (class Choice)
16+
import Data.Profunctor.Closed (class Closed)
17+
import Data.Profunctor.Strong (class Strong)
18+
import Data.Tuple (Tuple(..))
1019

1120
-- | `Star` turns a `Functor` into a `Profunctor`.
21+
-- |
22+
-- | `Star f` is also the Kleisli category for `f`
1223
newtype Star f a b = Star (a -> f b)
1324

1425
-- | Unwrap a value of type `Star f a b`.
1526
unStar :: forall f a b. Star f a b -> a -> f b
1627
unStar (Star f) = f
1728

29+
instance semigroupoidStar :: Bind f => Semigroupoid (Star f) where
30+
compose (Star f) (Star g) = Star \x -> g x >>= f
31+
32+
instance categoryStar :: Monad f => Category (Star f) where
33+
id = Star pure
34+
35+
instance functorStar :: Functor f => Functor (Star f a) where
36+
map f (Star g) = Star (map f <<< g)
37+
38+
instance invariantStar :: Invariant f => Invariant (Star f a) where
39+
imap f g (Star h) = Star (imap f g <<< h)
40+
41+
instance applyStar :: Apply f => Apply (Star f a) where
42+
apply (Star f) (Star g) = Star \a -> f a <*> g a
43+
44+
instance applicativeStar :: Applicative f => Applicative (Star f a) where
45+
pure a = Star \_ -> pure a
46+
47+
instance bindStar :: Bind f => Bind (Star f a) where
48+
bind (Star m) f = Star \x -> m x >>= \a -> unStar (f a) x
49+
50+
instance monadStar :: Monad f => Monad (Star f a)
51+
52+
instance altStar :: Alt f => Alt (Star f a) where
53+
alt (Star f) (Star g) = Star \a -> f a <|> g a
54+
55+
instance plusStar :: Plus f => Plus (Star f a) where
56+
empty = Star \_ -> empty
57+
58+
instance alternativeStar :: Alternative f => Alternative (Star f a)
59+
60+
instance monadZeroStar :: MonadZero f => MonadZero (Star f a)
61+
62+
instance monadPlusStar :: MonadPlus f => MonadPlus (Star f a)
63+
64+
instance distributiveStar :: Distributive f => Distributive (Star f a) where
65+
distribute f = Star \a -> collect ((_ $ a) <<< unStar) f
66+
collect f = distribute <<< map f
67+
1868
instance profunctorStar :: Functor f => Profunctor (Star f) where
1969
dimap f g (Star ft) = Star (f >>> ft >>> map g)
2070

@@ -25,3 +75,6 @@ instance strongStar :: Functor f => Strong (Star f) where
2575
instance choiceStar :: Applicative f => Choice (Star f) where
2676
left (Star f) = Star $ either (map Left <<< f) (pure <<< Right)
2777
right (Star f) = Star $ either (pure <<< Left) (map Right <<< f)
78+
79+
instance closedStar :: Distributive f => Closed (Star f) where
80+
closed (Star f) = Star \g -> distribute (f <<< g)

0 commit comments

Comments
 (0)