2023-03-07 22:15:08 -05:00
|
|
|
||| This module contains the Profunctor interface itself, along with a few
|
|
|
|
||| examples of profunctors.
|
2023-03-04 23:31:48 -05:00
|
|
|
module Data.Profunctor.Types
|
|
|
|
|
|
|
|
import Data.Contravariant
|
|
|
|
import Data.Morphisms
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Profunctor interface
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
||| An interface for (self-enriched) profunctors `Idr -/-> Idr`.
|
|
|
|
|||
|
|
|
|
||| Formally, a profunctor is a binary functor that is contravariant in its
|
|
|
|
||| first argument and covariant in its second. A common example of a profunctor
|
|
|
|
||| is the (non-dependent) function type.
|
|
|
|
|||
|
|
|
|
||| Implementations can be defined by specifying either `dimap` or both `lmap`
|
|
|
|
||| and `rmap`.
|
|
|
|
|||
|
|
|
|
||| Laws:
|
|
|
|
||| * `dimap id id = id`
|
|
|
|
||| * `dimap (f . g) (h . i) = dimap g h . dimap f i`
|
2023-03-04 23:31:48 -05:00
|
|
|
public export
|
|
|
|
interface Profunctor p where
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Map over both parameters of a profunctor at the same time, with the
|
|
|
|
||| left function argument mapping contravariantly.
|
2023-03-04 23:31:48 -05:00
|
|
|
dimap : (a -> b) -> (c -> d) -> p b c -> p a d
|
|
|
|
dimap f g = lmap f . rmap g
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Map contravariantly over the first parameter of a profunctor.
|
2023-03-04 23:31:48 -05:00
|
|
|
lmap : (a -> b) -> p b c -> p a c
|
|
|
|
lmap f = dimap f id
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Map covariantly over the second parameter of a profunctor.
|
2023-03-04 23:31:48 -05:00
|
|
|
rmap : (b -> c) -> p a b -> p a c
|
|
|
|
rmap = dimap id
|
|
|
|
|
|
|
|
|
2023-03-04 23:57:12 -05:00
|
|
|
infix 0 :->
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A transformation between profunctors that preserves their type parameters.
|
|
|
|
|||
|
|
|
|
||| Formally, this is a natural transformation of functors `Idrᵒᵖ * Idr => Idr`.
|
|
|
|
|||
|
|
|
|
||| If the transformation is `tr`, then we have the following law:
|
|
|
|
||| * `tr . dimap f g = dimap f g . tr`
|
2023-03-04 23:57:12 -05:00
|
|
|
public export
|
|
|
|
0 (:->) : (p, q : k -> k' -> Type) -> Type
|
2023-03-06 10:52:28 -05:00
|
|
|
p :-> q = forall a, b. p a b -> q a b
|
2023-03-04 23:57:12 -05:00
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Implementations for existing types
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Profunctor Morphism where
|
|
|
|
dimap f g (Mor h) = Mor (g . h . f)
|
|
|
|
lmap f (Mor g) = Mor (g . f)
|
|
|
|
rmap = map
|
|
|
|
|
|
|
|
namespace Profunctor
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A named implementation of `Profunctor` for function types.
|
|
|
|
||| Use this to avoid having to use a type wrapper like `Morphism`.
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
[Function] Profunctor (\a,b => a -> b) where
|
|
|
|
dimap f g h = g . h . f
|
|
|
|
lmap = flip (.)
|
|
|
|
rmap = (.)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor f => Profunctor (Kleislimorphism f) where
|
|
|
|
dimap f g (Kleisli h) = Kleisli (map g . h . f)
|
|
|
|
lmap f (Kleisli g) = Kleisli (g . f)
|
|
|
|
rmap = map
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
2023-03-08 13:30:55 -05:00
|
|
|
-- New profunctor types
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Lift a functor into a profunctor in the return type.
|
|
|
|
|||
|
|
|
|
||| This type is equivalent to `Kleislimorphism` except for the polymorphic type
|
|
|
|
||| of `b`.
|
2023-03-04 23:31:48 -05:00
|
|
|
public export
|
2023-03-04 23:56:35 -05:00
|
|
|
record Star {0 k : Type} (f : k -> Type) a (b : k) where
|
2023-03-04 23:31:48 -05:00
|
|
|
constructor MkStar
|
|
|
|
applyStar : a -> f b
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor f => Functor (Star f a) where
|
|
|
|
map f (MkStar g) = MkStar (map f . g)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Applicative f => Applicative (Star f a) where
|
|
|
|
pure = MkStar . const . pure
|
|
|
|
MkStar f <*> MkStar g = MkStar (\x => f x <*> g x)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Monad f => Monad (Star f a) where
|
|
|
|
MkStar f >>= g = MkStar $ \x => do
|
|
|
|
a <- f x
|
|
|
|
applyStar (g a) x
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Contravariant f => Contravariant (Star f a) where
|
|
|
|
contramap f (MkStar g) = MkStar (contramap f . g)
|
|
|
|
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor f => Profunctor (Star f) where
|
|
|
|
dimap f g (MkStar h) = MkStar (map g . h . f)
|
|
|
|
lmap f (MkStar g) = MkStar (g . f)
|
|
|
|
rmap f (MkStar g) = MkStar (map f . g)
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Lift a functor into a profunctor in the argument type.
|
2023-03-04 23:31:48 -05:00
|
|
|
public export
|
2023-03-04 23:56:35 -05:00
|
|
|
record Costar {0 k : Type} (f : k -> Type) (a : k) b where
|
2023-03-04 23:31:48 -05:00
|
|
|
constructor MkCostar
|
|
|
|
applyCostar : f a -> b
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor (Costar f a) where
|
|
|
|
map f (MkCostar g) = MkCostar (f . g)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Applicative (Costar f a) where
|
|
|
|
pure = MkCostar . const
|
|
|
|
MkCostar f <*> MkCostar g = MkCostar (\x => f x (g x))
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Monad (Costar f a) where
|
|
|
|
MkCostar f >>= g = MkCostar (\x => applyCostar (g (f x)) x)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor f => Profunctor (Costar f) where
|
|
|
|
dimap f g (MkCostar h) = MkCostar (g . h . map f)
|
|
|
|
lmap f (MkCostar g) = MkCostar (g . map f)
|
|
|
|
rmap f (MkCostar g) = MkCostar (f . g)
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The profunctor that ignores its argument type.
|
|
|
|
||| Equivalent to `const id` up to isomorphism.
|
2023-03-04 23:31:48 -05:00
|
|
|
public export
|
2023-03-04 23:56:35 -05:00
|
|
|
record Tagged {0 k : Type} (a : k) b where
|
2023-03-04 23:35:26 -05:00
|
|
|
constructor Tag
|
2023-03-06 16:44:26 -05:00
|
|
|
runTagged : b
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Retag the value with a different type-level parameter.
|
2023-03-04 23:31:48 -05:00
|
|
|
public export
|
|
|
|
retag : Tagged a c -> Tagged b c
|
2023-03-04 23:35:26 -05:00
|
|
|
retag (Tag x) = Tag x
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Functor (Tagged a) where
|
2023-03-04 23:35:26 -05:00
|
|
|
map f (Tag x) = Tag (f x)
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Applicative (Tagged a) where
|
2023-03-04 23:35:26 -05:00
|
|
|
pure = Tag
|
|
|
|
Tag f <*> Tag x = Tag (f x)
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Monad (Tagged a) where
|
2023-03-06 16:44:26 -05:00
|
|
|
join = runTagged
|
2023-03-04 23:35:26 -05:00
|
|
|
Tag x >>= f = f x
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Foldable (Tagged a) where
|
2023-03-04 23:35:26 -05:00
|
|
|
foldr f x (Tag y) = f y x
|
|
|
|
foldl f x (Tag y) = f x y
|
2023-03-04 23:31:48 -05:00
|
|
|
null = const False
|
2023-03-04 23:35:26 -05:00
|
|
|
foldlM f x (Tag y) = f x y
|
|
|
|
toList (Tag x) = [x]
|
|
|
|
foldMap f (Tag x) = f x
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Traversable (Tagged a) where
|
2023-03-04 23:35:26 -05:00
|
|
|
traverse f (Tag x) = map Tag (f x)
|
2023-03-04 23:31:48 -05:00
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-04 23:31:48 -05:00
|
|
|
Profunctor Tagged where
|
2023-03-04 23:35:26 -05:00
|
|
|
dimap _ f (Tag x) = Tag (f x)
|
2023-03-04 23:31:48 -05:00
|
|
|
lmap = const retag
|
2023-03-04 23:35:26 -05:00
|
|
|
rmap f (Tag x) = Tag (f x)
|
2023-03-08 15:05:07 -05:00
|
|
|
|
|
|
|
|
|
|
|
||| `Forget r` is equivalent to `Star (Const r)`.
|
|
|
|
public export
|
|
|
|
record Forget {0 k : Type} r a (b : k) where
|
|
|
|
constructor MkForget
|
|
|
|
runForget : a -> r
|
|
|
|
|
|
|
|
public export
|
|
|
|
reforget : Forget r a b -> Forget r a c
|
|
|
|
reforget (MkForget k) = MkForget k
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Functor (Forget r a) where
|
|
|
|
map _ = reforget
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Contravariant (Forget {k=Type} r a) where
|
|
|
|
contramap _ = reforget
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Monoid r => Applicative (Forget r a) where
|
|
|
|
pure _ = MkForget (const neutral)
|
|
|
|
MkForget f <*> MkForget g = MkForget (f <+> g)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Monoid r => Monad (Forget {k=Type} r a) where
|
|
|
|
join = reforget
|
|
|
|
(>>=) = reforget .: const
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Foldable (Forget r a) where
|
|
|
|
foldr _ x _ = x
|
|
|
|
foldl _ x _ = x
|
|
|
|
null = const True
|
|
|
|
foldlM _ x _ = pure x
|
|
|
|
toList _ = []
|
|
|
|
foldMap _ _ = neutral
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Traversable (Forget r a) where
|
|
|
|
traverse _ = pure . reforget
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Profunctor (Forget r) where
|
|
|
|
dimap f _ (MkForget k) = MkForget (k . f)
|
|
|
|
lmap f (MkForget k) = MkForget (k . f)
|
|
|
|
rmap = map
|
|
|
|
|
|
|
|
|
|
|
|
||| `Coforget r` is equivalent to `Costar (Const r)`.
|
|
|
|
public export
|
|
|
|
record Coforget {0 k : Type} r (a : k) b where
|
|
|
|
constructor MkCoforget
|
|
|
|
runCoforget : r -> b
|
|
|
|
|
|
|
|
public export
|
|
|
|
recoforget : Coforget r a c -> Coforget r b c
|
|
|
|
recoforget (MkCoforget k) = MkCoforget k
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Functor (Coforget r a) where
|
|
|
|
map f (MkCoforget k) = MkCoforget (f . k)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
|
|
|
Bifunctor (Coforget r) where
|
|
|
|
bimap _ f (MkCoforget k) = MkCoforget (f . k)
|
|
|
|
mapFst _ = recoforget
|
|
|
|
mapSnd = map
|
|
|
|
|
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Applicative (Coforget r a) where
|
|
|
|
pure = MkCoforget . const
|
|
|
|
MkCoforget f <*> MkCoforget g = MkCoforget (\r => f r (g r))
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
2023-03-08 15:05:07 -05:00
|
|
|
Monad (Coforget r a) where
|
|
|
|
MkCoforget k >>= f = MkCoforget (\r => runCoforget (f $ k r) r)
|
|
|
|
|
2023-03-30 13:32:45 -04:00
|
|
|
public export
|
|
|
|
Profunctor (Coforget r) where
|
2023-03-08 15:05:07 -05:00
|
|
|
dimap _ f (MkCoforget k) = MkCoforget (f . k)
|
|
|
|
lmap _ = recoforget
|
|
|
|
rmap = map
|
2023-03-30 14:08:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Identity functor
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
-- A few convenience definitions for use in other modules.
|
|
|
|
|
|
|
|
public export
|
|
|
|
[FunctorId] Functor Prelude.id where
|
|
|
|
map = id
|
|
|
|
|
|
|
|
public export
|
|
|
|
[ApplicativeId] Applicative Prelude.id using FunctorId where
|
|
|
|
pure = id
|
|
|
|
(<*>) = id
|
|
|
|
|
|
|
|
public export
|
|
|
|
[MonadId] Monad Prelude.id using ApplicativeId where
|
|
|
|
join = id
|
|
|
|
(>>=) = flip id
|
|
|
|
|
|
|
|
public export
|
|
|
|
[FoldableId] Foldable Prelude.id where
|
|
|
|
foldr = flip
|
|
|
|
foldl = id
|
|
|
|
null _ = False
|
|
|
|
foldlM = id
|
|
|
|
toList = pure
|
|
|
|
foldMap = id
|
|
|
|
|
|
|
|
public export
|
|
|
|
[TraversableId] Traversable Prelude.id using FunctorId FoldableId where
|
|
|
|
traverse = id
|