Massively improve usability by removing requirement for `Obj` constraints.

Instead, expect `morph a b` to evidence that `a` and `b` are objects,
and use `morph a a` equivalently to how `Obj morph a` was used before.
This results in some redundant parameters in categories in which every
type of a kind is an object ('nice categories', `NiceCat`),
but those can often be avoided with synonyms, and it's far better
than the constraint hell and `Dict`-passing I had to deal with before.
master
James T. Martin 2021-03-01 16:21:38 -08:00
parent d90d3ad679
commit 05ddc84fff
Signed by: james
GPG Key ID: 4B7F3DA9351E577C
15 changed files with 227 additions and 178 deletions

View File

@ -1,42 +1,55 @@
module Category.Base where
-- The default type signatures for `idL` and `idR` trigger
-- redundant constraints because `NiceCat` requires `Category`
-- but it's forced to require `Category` because that's where it's defined.
-- This seems like it might be a bug.
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
module Category.Base
( Category, Obj, idL, idR, (.)
, NiceCat, id
, Yoneda (Op), Op, getOp
) where
import Data.Dict
import Data.Kind (Constraint, FUN, Type)
import GHC.Types (Multiplicity)
-- | A one-parameter typeclass which is always implemented.
type Unconst1 :: i -> Constraint
class Unconst1 a
instance Unconst1 a
-- | Objects are uniquely identified by their identity arrow.
type Obj :: (i -> i -> j) -> i -> j
type Obj morph a = morph a a
type Category :: forall i. (i -> i -> Type) -> Constraint
-- Scoped type variables does not make `i` in scope with standalone kind signatures,
-- so this redundant type annotation is necessary.
class Category (morph :: i -> i -> Type) where
type Obj morph :: i -> Constraint
type Obj _morph = Unconst1
obj :: morph a b -> Dict (Obj morph a, Obj morph b)
default obj :: forall a b. Obj morph ~ Unconst1 => morph a b -> Dict (Obj morph a, Obj morph b)
obj _ = Dict
class Category morph where
idL :: morph a b -> Obj morph a
default idL :: NiceCat morph => morph a b -> Obj morph a
idL _ = id
idR :: morph a b -> Obj morph b
default idR :: NiceCat morph => morph a b -> Obj morph b
idR _ = id
id :: Obj morph a => morph a a
-- | Associative composition of morphisms.
(.) :: morph b c -> morph a b -> morph a c
instance forall (m :: Multiplicity). Category (FUN m) where
id = \x -> x
type NiceCat :: forall i. (i -> i -> Type) -> Constraint
class Category morph => NiceCat morph where
id :: Obj morph a
instance forall m. Category (FUN m) where
f . g = \x -> f (g x)
instance forall m. NiceCat (FUN m) where
id = \x -> x
type Yoneda :: (i -> i -> Type) -> i -> i -> Type
newtype Yoneda morph a b = Op { getOp :: morph b a }
instance Category morph => Category (Yoneda morph) where
type Obj (Yoneda morph) = Obj morph
obj (Op f) = case obj f of Dict -> Dict
id = Op id
Op f . Op g = Op (g . f)
type Op :: (i -> i -> Type) -> i -> i -> Type
type family Op morph where
Op (Yoneda morph) = morph
Op morph = Yoneda morph
instance Category morph => Category (Yoneda morph) where
idL (Op f) = Op (idR f)
idR (Op f) = Op (idL f)
Op f . Op g = Op (g . f)
instance NiceCat morph => NiceCat (Yoneda morph) where
id = Op id

View File

@ -1,5 +1,8 @@
{-# LANGUAGE UndecidableSuperClasses #-}
module Category.Constraint where
module Category.Constraint
( (:-) (Sub), (\\)
, ProdC
) where
import Category.Base
import Category.Functor
@ -14,12 +17,13 @@ data (:-) c d = Sub (c => Dict d)
r \\ Sub Dict = r
instance Category (:-) where
id = Sub Dict
f . g = Sub (Dict \\ f \\ g)
instance NiceCat (:-) where
id = Sub Dict
instance Functor (Nat (->) (:-)) (Yoneda (:-)) (:-) where
map_ _ _ = Dict
map (Op (Sub f)) = Nat \(Sub g) -> Sub case f of Dict -> case g of Dict -> Dict
map (Op (Sub f)) = Nat \_ (Sub g) -> Sub case f of Dict -> case g of Dict -> Dict
instance Functor (->) (:-) ((:-) a) where
map = (.)
@ -35,17 +39,16 @@ instance (c, d) => ProdC c d
-- (up to isomorphism), although I haven't seriously thought about it at all.
instance Functor (Nat (:-) (:-)) (:-) ProdC where
map_ _ _ = Dict
map (Sub f) = Nat (Sub case f of Dict -> Dict)
map (Sub f) = Nat_ (Sub case f of Dict -> Dict)
instance Functor (:-) (:-) (ProdC a) where
map (Sub f) = Sub case f of Dict -> Dict
instance Monoidal (:-) ProdC where
instance TensorProduct (:-) ProdC where
type Unit (:-) ProdC = ()
uil = Sub Dict
uir = Sub Dict
uel = Sub Dict
uer = Sub Dict
pal = Sub Dict
par = Sub Dict
prodIL _ = Sub Dict
prodIR _ = Sub Dict
prodEL _ = Sub Dict
prodER _ = Sub Dict
prodAL _ _ _ = Sub Dict
prodAR _ _ _ = Sub Dict

View File

@ -1,24 +1,18 @@
module Category.Enriched where
module Category.Enriched
( Enriched, eid, ecomp
) where
import Category.Base
import Category.Monoidal
import Data.Dict
import Data.Kind (Constraint, FUN, Type)
import GHC.Types (Multiplicity (One))
class Monoidal over prod => Enriched (over :: j -> j -> Type) prod (morph :: i -> i -> j) where
type EObj over prod morph :: i -> Constraint
type EObj _over _prod _morph = Unconst1
eobj :: proxy prod -> over (Unit over prod) (morph a b) -> Dict (EObj over prod morph a, EObj over prod morph b)
default eobj :: forall proxy a b. EObj over prod morph ~ Unconst1 => proxy prod -> over (Unit over prod) (morph a b) -> Dict (EObj over prod morph a, EObj over prod morph b)
eobj _ _ = Dict
eid :: EObj over prod morph a => proxy prod -> over (Unit over prod) (morph a a)
type Enriched :: (j -> j -> Type) -> (j -> j -> j) -> (i -> i -> j) -> Constraint
class TensorProduct over prod => Enriched over prod morph where
eid :: proxy prod -> over (Unit over prod) (Obj morph a)
ecomp :: over (prod (morph b c) (morph a b)) (morph a c)
instance Category morph => Enriched (->) (,) morph where
type EObj (->) (,) morph = Obj morph
eobj _ f = obj (f ())
instance NiceCat morph => Enriched (->) (,) morph where
eid _ = \() -> id
ecomp = \(f, g) -> f . g

View File

@ -1,8 +1,15 @@
{-# LANGUAGE UndecidableInstances #-}
module Category.Functor where
module Category.Functor
( Functor, map
, Endo, Endofunctor, endomap
, Contravariant, contramap
, Bifunctor, bimap, first, second
, Profunctor, dimap, lmap, rmap
, Nat (Nat), runNat, pattern Nat_, natId
, Const (Const), getConst
) where
import Category.Base
import Data.Dict
import Data.Either (Either (Left, Right))
import Data.Kind (Constraint, FUN, Type)
import Data.Maybe (Maybe (Nothing, Just))
@ -10,9 +17,6 @@ import Data.Proxy
type Functor :: (j -> j -> Type) -> (i -> i -> Type) -> (i -> j) -> Constraint
class (Category dest, Category src) => Functor dest src f where
map_ :: Obj src a => proxy dest -> proxy' src -> Dict (Obj dest (f a))
default map_ :: forall proxy proxy' a. Obj dest ~ Unconst1 => proxy dest -> proxy' src -> Dict (Obj dest (f a))
map_ _ _ = Dict
map :: src a b -> dest (f a) (f b)
type Endo f a = f a a
@ -31,55 +35,67 @@ instance {-# INCOHERENT #-} Functor dest (Yoneda src) f => Contravariant dest sr
instance {-# INCOHERENT #-} Functor dest src f => Contravariant dest (Yoneda src) f where
contramap (Op f) = map f
-- FIXME:
-- I'm not convinced this definition is sufficient.
-- Don't feel like explaining why. Hopefully it won't be too long before I fix it.
-- I'd hate to forget~
type Bifunctor :: (j -> j -> Type) -> (i -> i -> Type) -> (i -> i -> j) -> Constraint
class (Functor (Nat dest src) src f, forall x. Functor dest src (f x)) => Bifunctor dest src f
instance (Functor (Nat dest src) src f, forall x. Functor dest src (f x)) => Bifunctor dest src f
bimap :: forall dest src f a b c d. Bifunctor dest src f => src a c -> src b d -> dest (f a b) (f c d)
bimap f g = case obj g of Dict -> runNat @_ @_ @dest @src (map f) . map g
--first :: forall dest src f a b c d. Bifunctor dest src f => src a b -> dest (f a c) (f b c)
--first f = runNat @_ @_ @dest @src (map f)
bimap :: Bifunctor dest src f => src a c -> src b d -> dest (f a b) (f c d)
bimap f g = runNat (map f) (idR g) . map g
-- FIXME: A NiceCat dependency should not be necessary here,
-- this most likely means that my definition of Bifunctor is inadequate.
first :: forall dest src f a b c. (Bifunctor dest src f, NiceCat src) => src a b -> dest (f a c) (f b c)
first f = runNat (map f) (id :: Obj src c)
second :: Bifunctor dest src f => src b c -> dest (f a b) (f a c)
second g = map g
type Profunctor :: (j -> j -> Type) -> (i -> i -> Type) -> (i -> i -> j) -> Constraint
class (Functor (Nat dest src) (Yoneda src) f, forall x. Functor dest src (f x)) => Profunctor dest src f
instance (Functor (Nat dest src) (Yoneda src) f, forall x. Functor dest src (f x)) => Profunctor dest src f
dimap :: forall dest src f a b c d. Profunctor dest src f => src a b -> src c d -> dest (f b c) (f a d)
dimap f g = case obj g of Dict -> runNat @_ @_ @dest @src (map (Op f)) . map g
dimap :: Profunctor dest src f => src a b -> src c d -> dest (f b c) (f a d)
dimap f g = runNat (map (Op f)) (idR g) . map g
lmap :: forall dest src f a b c. (Profunctor dest src f, NiceCat src) => src a b -> dest (f b c) (f a c)
lmap f = runNat (map (Op f)) (id :: Obj src c)
rmap :: Profunctor dest src f => src b c -> dest (f a b) (f a c)
rmap f = map f
type Nat :: (j -> j -> Type) -> (i -> i -> Type) -> (i -> j) -> (i -> j) -> Type
data Nat dest src f g = (Functor dest src f, Functor dest src g) => Nat { runNat :: !(forall a. Obj src a => dest (f a) (g a)) }
data Nat dest src f g = (Functor dest src f, Functor dest src g) => Nat { runNat :: !(forall a. Obj src a -> dest (f a) (g a)) }
instance Category dest => Category (Nat dest src) where
type Obj (Nat dest src) = Functor dest src
obj (Nat _) = Dict
id :: forall f. Obj (Nat dest src) f => Nat dest src f f
id = Nat id'
where id' :: forall a. Obj src a => dest (f a) (f a)
id' = case map_ (Proxy @dest) (Proxy @src) :: Dict (Obj dest (f a)) of Dict -> id
Nat f . Nat g = Nat (f . g)
type Nat_' :: (j -> j -> Type) -> (i -> i -> Type) -> (i -> j) -> (i -> j) -> Type
data Nat_' dest src f g = (Functor dest src f, Functor dest src g) => Nat_' !(forall a. dest (f a) (g a))
nat_' :: NiceCat src => Nat dest src f g -> Nat_' dest src f g
nat_' (Nat f) = Nat_' (f id)
pattern Nat_ :: forall dest src f g. NiceCat src => (Functor dest src f, Functor dest src g) => (forall a. dest (f a) (g a)) -> Nat dest src f g
{-# COMPLETE Nat_ #-}
pattern Nat_ f <- (nat_' -> Nat_' f)
where Nat_ f = Nat \_ -> f
instance Category (Nat dest src) where
idL (Nat _) = Nat map
idR (Nat _) = Nat map
Nat f . Nat g = Nat \x -> (f x . g x)
natId :: Functor dest src f => Obj (Nat dest src) f
natId = Nat map
instance (forall f. Functor dest src f) => NiceCat (Nat dest src) where
id = natId
instance Functor (->) (FUN m) (FUN m a) where
map f = \g -> f . g
instance Functor (Nat (->) (FUN m)) (Yoneda (FUN m)) (FUN m) where
map_ _ _ = Dict
map (Op f) = Nat \g -> g . f
map (Op f) = Nat \_ g -> g . f
instance Functor (Nat (FUN m) (FUN m)) (FUN m) (,) where
map_ _ _ = Dict
map f = Nat \(x, y) -> (f x, y)
map f = Nat \_ (x, y) -> (f x, y)
instance Functor (FUN m) (FUN m) ((,) a) where
map f = \(x, y) -> (x, f y)
instance Functor (Nat (FUN m) (FUN m)) (FUN m) Either where
map_ _ _ = Dict
map f = Nat \case
map f = Nat \_ -> \case
Left y -> Left (f y)
Right x -> Right x
@ -100,8 +116,7 @@ type Const :: Type -> i -> Type
newtype Const a b = Const { getConst :: a }
instance Functor (Nat (->) (->)) (->) Const where
map_ _ _ = Dict
map f = Nat \(Const x) -> Const (f x)
map f = Nat \_ (Const x) -> Const (f x)
instance {-# INCOHERENT #-} Category src => Functor (->) src (Const a) where
map _ = \(Const x) -> Const x

View File

@ -1,4 +1,4 @@
module Category.Groupoid where
module Category.Groupoid (Groupoid, inv) where
import Category.Base
import Data.Kind (Constraint, Type)

View File

@ -1,10 +1,13 @@
module Category.Monoid where
{-# LANGUAGE UndecidableInstances #-}
module Category.Monoid
( Monoid, empty
, (>>=)
) where
import Category.Base
import Category.Functor
import Category.Monoidal
import Category.Semigroup
import Data.Dict
import Data.Kind (Constraint, Type)
import Data.Maybe (Maybe (Just))
import Data.Proxy
@ -14,9 +17,13 @@ class Semigroup morph prod m => Monoid morph prod m where
empty :: proxy morph -> proxy' prod -> morph (Unit morph prod) m
instance Monoid (Nat (->) (->)) Compose Maybe where
empty _ _ = Nat \(Identity x) -> Just x
empty _ _ = Nat_ \(Identity x) -> Just x
-- | A monad is a monoid object in the monoidal category of endofunctors and natural transformations between them!
class Monoid (Nat (->) (->)) Compose m => Monad m
instance Monoid (Nat (->) (->)) Compose m => Monad m
(>>=) :: forall f a b. Monoid (Nat (->) (->)) Compose f => f a -> (a -> f b) -> f b
m >>= f = runNat (append @_ @(Nat (->) (->))) m'
where m' :: Compose f f b
m' = case obj (empty @_ @_ @_ @f (Proxy @(Nat (->) (->))) (Proxy @Compose)) of Dict -> Compose (map f m)
m >>= f = runNat (append @_ @(Nat (->) (->))) id (lemma (Compose (map f m)))
where lemma :: forall c. (Functor (->) (->) f => c) -> c
lemma x = case empty (Proxy @(Nat (->) (->))) (Proxy @Compose) :: Nat (->) (->) Identity f of Nat _ -> x

View File

@ -1,58 +1,68 @@
module Category.Monoidal where
module Category.Monoidal
( TensorProduct, Unit, unitObj, prodObj, prodIL, prodIR, prodEL, prodER, prodAL, prodAR
, Compose (Compose), getCompose
, Identity (Identity), getIdentity
) where
import Category.Base
import Category.Functor
import Data.Dict
import Data.Either (Either (Left, Right))
import Data.Kind (Constraint, FUN, Type)
import Data.Void (Void)
-- FIXME: Rename this.
-- | A category is monoidal if it has a product and a unit for that product.
-- A category can have multiple tensor products and be monoidal in multiple ways,
-- including the category of types itself,
-- so instead of using a @Monoidal@ typeclass, we use a @TensorProduct@ typeclass.
-- Only we actually don't, because I haven't had a chance to rename it yet.
type Monoidal :: (i -> i -> Type) -> (i -> i -> i) -> Constraint
class Endo Bifunctor morph prod => Monoidal (morph :: i -> i -> Type) prod where
-- FIXME: Fix all of these garbage names. `uil`? `pal`? seriously?
type TensorProduct :: (i -> i -> Type) -> (i -> i -> i) -> Constraint
class Endo Bifunctor morph prod => TensorProduct (morph :: i -> i -> Type) prod where
type Unit morph prod :: i
prodObj :: (Obj morph a, Obj morph b) => proxy morph -> proxy' prod -> proxy'' a -> proxy''' b -> Dict (Obj morph (prod a b))
default prodObj :: Obj morph ~ Unconst1 => proxy morph -> proxy' prod -> proxy'' a -> proxy''' b -> Dict (Obj morph (prod a b))
prodObj _ _ _ _ = Dict
unitObj :: proxy morph -> proxy' prod -> Dict (Obj morph (Unit morph prod))
default unitObj :: Obj morph ~ Unconst1 => proxy morph -> proxy' prod -> Dict (Obj morph (Unit morph prod))
unitObj _ _ = Dict
uil :: Obj morph a => morph a (prod (Unit morph prod) a)
uir :: Obj morph a => morph a (prod a (Unit morph prod))
uel :: Obj morph a => morph (prod (Unit morph prod) a) a
uer :: Obj morph a => morph (prod a (Unit morph prod)) a
pal :: (Obj morph a, Obj morph b, Obj morph c) => morph (prod a (prod b c)) (prod (prod a b) c)
par :: (Obj morph a, Obj morph b, Obj morph c) => morph (prod (prod a b) c) (prod a (prod b c))
-- | The unit is an object.
unitObj :: proxy prod -> Obj morph (Unit morph prod)
default unitObj :: NiceCat morph => proxy prod -> Obj morph (Unit morph prod)
unitObj _ = id
instance Monoidal (FUN m) (,) where
-- | Given two objects, their product is also an object.
prodObj :: Obj morph a -> Obj morph b -> Obj morph (prod a b)
default prodObj :: NiceCat morph => Obj morph a -> Obj morph b -> Obj morph (prod a b)
prodObj _ _ = id
-- | Introduce a product with the value injected into the left side.
prodIL :: Obj morph a -> morph a (prod a (Unit morph prod))
-- | Introduce a product with the value injected into the right side.
prodIR :: Obj morph a -> morph a (prod (Unit morph prod) a)
-- | Eliminate a product with the value projected from the left side.
prodEL :: Obj morph a -> morph (prod a (Unit morph prod)) a
-- | Eliminate a product with the value projected from the right side.
prodER :: Obj morph a -> morph (prod (Unit morph prod) a) a
-- | Reassociate a product, nesting it to the left.
prodAL :: Obj morph a -> Obj morph b -> Obj morph c -> morph (prod a (prod b c)) (prod (prod a b) c)
-- | Reassociate a product, nesting it to the right.
prodAR :: Obj morph a -> Obj morph b -> Obj morph c -> morph (prod (prod a b) c) (prod a (prod b c))
instance TensorProduct (FUN m) (,) where
type Unit (FUN m) (,) = ()
uil = \x -> ((), x)
uir = \x -> (x, ())
uel = \((), x) -> x
uer = \(x, ()) -> x
pal = \(x, (y, z)) -> ((x, y), z)
par = \((x, y), z) -> (x, (y, z))
prodIL _ = \x -> (x, ())
prodIR _ = \x -> ((), x)
prodEL _ = \(x, ()) -> x
prodER _ = \((), x) -> x
prodAL _ _ _ = \(x, (y, z)) -> ((x, y), z)
prodAR _ _ _ = \((x, y), z) -> (x, (y, z))
instance Monoidal (FUN m) Either where
instance TensorProduct (FUN m) Either where
type Unit (FUN m) Either = Void
uil = Right
uir = Left
uel (Left x) = (\case{}) x
uel (Right x) = x
uer (Left x) = x
uer (Right x) = (\case{}) x
pal (Left x) = Left (Left x)
pal (Right (Left x)) = Left (Right x)
pal (Right (Right x)) = Right x
par (Left (Left x)) = Left x
par (Left (Right x)) = Right (Left x)
par (Right x) = Right (Right x)
prodIL _ = Left
prodIR _ = Right
prodEL _ (Left x) = x
prodEL _ (Right x) = (\case{}) x
prodER _ (Left x) = (\case{}) x
prodER _ (Right x) = x
prodAL _ _ _ (Left x) = Left (Left x)
prodAL _ _ _ (Right (Left x)) = Left (Right x)
prodAL _ _ _ (Right (Right x)) = Right x
prodAR _ _ _ (Left (Left x)) = Left x
prodAR _ _ _ (Left (Right x)) = Right (Left x)
prodAR _ _ _ (Right x) = Right (Right x)
data Compose f g x = (Functor (->) (->) f, Functor (->) (->) g) => Compose { getCompose :: !(f (g x)) }
newtype Identity x = Identity { getIdentity :: x }
@ -60,24 +70,22 @@ newtype Identity x = Identity { getIdentity :: x }
instance Functor (FUN m) (FUN m) Identity where
map f = \(Identity x) -> Identity (f x)
instance Functor (->) (->) (Compose f g) where
map f = \(Compose x) -> Compose (map @_ @_ @(->) @(->) (map f) x)
instance Functor (Nat (Nat (->) (->)) (Nat (->) (->))) (Nat (->) (->)) Compose where
map_ _ _ = Dict
map (Nat f) = Nat (Nat \(Compose x) -> Compose (f x))
map (Nat f) = Nat \(Nat _) -> Nat \_ (Compose x) -> Compose (f id x)
instance Functor (Nat (->) (->)) (Nat (->) (->)) (Compose f) where
map_ _ _ = Dict
map (Nat f) = Nat \(Compose x) -> Compose (map f x)
map (Nat f) = Nat \_ (Compose x) -> Compose (map (f id) x)
instance Monoidal (Nat (->) (->)) Compose where
instance Functor (->) (->) (Compose (f :: Type -> Type) g) where
map f = \(Compose x) -> Compose (map @_ @_ @_ @(->) (map f) x)
instance TensorProduct (Nat (->) (->)) Compose where
type Unit (Nat (->) (->)) Compose = Identity
prodObj _ _ _ _ = Dict
unitObj _ _ = Dict
uil = Nat \x -> Compose (Identity x)
uir = Nat \x -> Compose (map Identity x)
uel = Nat \(Compose (Identity x)) -> x
uer = Nat \(Compose x) -> map getIdentity x
pal = Nat \(Compose x) -> Compose (Compose (map getCompose x))
par = Nat \(Compose (Compose x)) -> Compose (map Compose x)
unitObj _ = natId
prodObj _ _ = natId
prodIL (Nat _) = Nat_ \x -> Compose (map Identity x)
prodIR (Nat _) = Nat_ \x -> Compose (Identity x)
prodEL (Nat _) = Nat_ \(Compose x) -> map getIdentity x
prodER (Nat _) = Nat_ \(Compose (Identity x)) -> x
prodAL (Nat _) (Nat _) (Nat _) = Nat_ \(Compose x) -> Compose (Compose (map getCompose x))
prodAR (Nat _) (Nat _) (Nat _) = Nat_ \(Compose (Compose x)) -> Compose (map Compose x)

View File

@ -1,4 +1,4 @@
module Category.Semigroup where
module Category.Semigroup (Semigroup, append) where
import Category.Functor
import Category.Monoidal
@ -6,11 +6,11 @@ import Data.Kind (Constraint, Type)
import Data.Maybe (Maybe (Nothing, Just))
type Semigroup :: (i -> i -> Type) -> (i -> i -> i) -> i -> Constraint
class Monoidal morph prod => Semigroup morph prod s where
class TensorProduct morph prod => Semigroup morph prod s where
append :: morph (prod s s) s
instance Semigroup (Nat (->) (->)) Compose Maybe where
append = Nat \(Compose x') -> case x' of
append = Nat \_ (Compose x') -> case x' of
Nothing -> Nothing
Just Nothing -> Nothing
Just (Just x) -> Just x

View File

@ -1,4 +1,4 @@
module Data.Dict where
module Data.Dict (Dict (Dict)) where
import Data.Kind (Constraint, Type)

View File

@ -1,8 +1,11 @@
module Data.Fin where
module Data.Fin
( Fin (FZ, FS)
, FinF (FZF, FSF)
, fin2nat
) where
import Category.Functor
import Category.Functor.Foldable
import Data.Dict
import Data.Identity
import Data.Kind (Type)
import Data.Nat
@ -16,24 +19,23 @@ data FinF r :: N -> Type where
type instance Base Fin = FinF
instance Functor (Nat (->) (:~:)) (Nat (->) (:~:)) FinF where
map_ _ _ = Dict
map :: forall f g. Nat (->) (:~:) f g -> Nat (->) (:~:) (FinF f) (FinF g)
map (Nat f) = Nat \case
map (Nat_ f) = Nat_ \case
FZF -> FZF
(FSF r) -> FSF (f r)
instance Recursive (Nat (->) (:~:)) Fin where
project = Nat \case
project = Nat_ \case
FZ -> FZF
(FS r) -> FSF r
instance Corecursive (Nat (->) (:~:)) Fin where
embed = Nat \case
embed = Nat_ \case
FZF -> FZ
(FSF r) -> FS r
fin2nat :: Nat (->) (:~:) Fin (Const N)
fin2nat = cata (Nat alg)
fin2nat = cata (Nat_ alg)
where alg :: FinF (Const N) n -> Const N n
alg FZF = Const Z
alg (FSF (Const n)) = Const (S n)

View File

@ -1,9 +1,8 @@
module Data.Identity where
module Data.Identity ((:~:) (Refl)) where
import Category.Base
import Category.Functor
import Category.Groupoid
import Data.Dict
import Data.Kind (Type)
type (:~:) :: i -> i -> Type
@ -11,9 +10,11 @@ data (:~:) :: i -> i -> Type where
Refl :: a :~: a
instance Category (:~:) where
id = Refl
Refl . Refl = Refl
instance NiceCat (:~:) where
id = Refl
instance Groupoid (:~:) where
inv Refl = Refl
@ -25,9 +26,7 @@ instance {-# INCOHERENT #-} Functor (->) (Yoneda (:~:)) f where
map (Op Refl) = id
instance {-# INCOHERENT #-} Functor (Nat (->) (:~:)) (:~:) f where
map_ _ _ = Dict
map Refl = id
instance {-# INCOHERENT #-} Functor (Nat (->) (:~:)) (Yoneda (:~:)) f where
map_ _ _ = Dict
map (Op Refl) = id

View File

@ -1,5 +1,10 @@
-- | The natural numbers and associated types and functions.
module Data.Nat where
module Data.Nat
( N (Z, S), inf
, NTyF (ZTyF, STyF)
, (:+)
, injective, rightZero
) where
import Category.Functor
import Category.Functor.Foldable
@ -42,8 +47,7 @@ data NTyF r n where
STyF :: r n -> NTyF r ('S n)
instance Functor (Nat (->) (:~:)) (Nat (->) (:~:)) NTyF where
map_ _ _ = Dict
map (Nat f) = Nat \case
map (Nat_ f) = Nat_ \case
ZTyF -> ZTyF
(STyF r) -> STyF (f r)
@ -60,12 +64,12 @@ instance Corecursive (->) N where
type instance Base (Ty N) = NTyF
instance Recursive (Nat (->) (:~:)) (Ty N) where
project = Nat \case
project = Nat_ \case
ZTy -> ZTyF
(STy r) -> STyF r
instance Corecursive (Nat (->) (:~:)) (Ty N) where
embed = Nat \case
embed = Nat_ \case
ZTyF -> ZTy
(STyF r) -> STy r

View File

@ -3,7 +3,7 @@
-- and doesn't let you control which arguments are implicit and which are explicit.
--
-- 'Proxy' provides a better alternative for passing explicit type arguments.
module Data.Proxy where
module Data.Proxy (Proxy (Proxy)) where
import Data.Kind (Type)

View File

@ -1,9 +1,12 @@
module Data.Vec where
module Data.Vec
( Vec (VZ, VS)
, VecF (VZF, VSF)
, index
) where
import Category.Base
import Category.Functor
import Category.Functor.Foldable
import Data.Dict
import Data.Fin
import Data.Identity
import Data.Kind (Type)
@ -21,20 +24,17 @@ data VecF a r :: N -> Type where
type instance Base (Vec a) = VecF a
instance Functor (Nat (->) (:~:)) (->) Vec where
map_ _ _ = Dict
map f = Nat \case
map f = Nat_ \case
VZ -> VZ
(VS x r) -> VS (f x) (runNat (map @_ @_ @(Nat (->) (:~:)) f) r)
(VS x r) -> VS (f x) (runNat (map @_ @_ @(Nat (->) (:~:)) f) id r)
instance Functor (Nat (->) (:~:)) (Nat (->) (:~:)) (VecF a) where
map_ _ _ = Dict
map (Nat f) = Nat \case
map (Nat_ f) = Nat_ \case
VZF -> VZF
(VSF x r) -> VSF x (f r)
instance Functor (Nat (Nat (->) (:~:)) (Nat (->) (:~:))) (->) VecF where
map_ _ _ = Dict
map f = Nat $ Nat \case
map f = Nat_ $ Nat_ \case
VZF -> VZF
(VSF x r) -> VSF (f x) r
@ -42,9 +42,9 @@ type Ixr :: (N -> Type) -> Type -> N -> Type
newtype Ixr ty r a = Ixr { getIxr :: ty a -> r }
indexer :: Nat (->) (:~:) Fin (Ixr (Vec a) a)
indexer = cata $ Nat \case
indexer = cata $ Nat_ \case
FZF -> Ixr \case VS x _ -> x
(FSF (Ixr r)) -> Ixr \case VS _ xs -> r xs
index :: Fin n -> Vec a n -> a
index = getIxr . runNat indexer
index = getIxr . runNat indexer id

View File

@ -23,7 +23,11 @@
--
-- This technique was first described in [Conor McBride's Hasochism paper](https://personal.cis.strath.ac.uk/conor.mcbride/pub/hasochism.pdf);
-- the idea to make a `Pi` typeclass was my own, but I'm sure it's been done before.
module Quantifier where
module Quantifier
( Forall (Forall), runForall
, Pi, Ty, depi
, PiC, TyC, depic
) where
import Data.Kind (Constraint, Type)
import Data.Maybe (Maybe (Nothing, Just))