lude

Haskell prelude alternative
git clone git://git.rr3.xyz/lude | git clone gits://git.rr3.xyz/lude
Log | Files | Refs | LICENSE

commit d81444ca049f02f7c0ae74eb4d0d849709ab01df
parent 65434a8b929548b0f5cf317d9cc89ed47efa6e5f
Author: Robert Russell <robert@rr3.xyz>
Date:   Thu, 10 Sep 2026 11:24:00 -0700

Reorganize

Diffstat:
Csrc/Lude.hs -> Todo/Lude.hs | 0
Msrc/Lude.hs | 629++-----------------------------------------------------------------------------
Asrc/Lude/Algebra.hs | 5+++++
Dsrc/Lude/Algebra/Algebra.hs | 80-------------------------------------------------------------------------------
Msrc/Lude/Algebra/Category.hs | 6++----
Msrc/Lude/Algebra/Category/Adjunction.hs | 2++
Asrc/Lude/Algebra/Category/Algebra.hs | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Lude/Algebra/Category/Core.hs | 2++
Asrc/Lude/Function.hs | 12++++++++++++
9 files changed, 114 insertions(+), 704 deletions(-)

diff --git a/src/Lude.hs b/Todo/Lude.hs diff --git a/src/Lude.hs b/src/Lude.hs @@ -1,623 +1,12 @@ module Lude ( --- Types, --- Constraint, --- Levity (..), --- RuntimeRep (..), --- Thunked, --- LRep, --- URep, --- Type, --- BoxedType, --- LType, --- UType, --- Kind, --- Unlift (..), --- Function --- const, --- fix, --- flip, --- ($), --- ($!), --- (&), --- (&!), --- Bool --- IsBool (..), --- Bool (..), --- (&&), --- (||), --- not, --- Category --- Category (identity, compose), --- (<.), --- (.>), --- Functor -{- -Functor, -void, -Compose (Compose, getCompose), -Const (Const, getConst), -Identity (Identity, runIdentity), -map, -($^), -for, -(^&), -flap, -(^$), -flor, -(&^), -(<<^), -(^>>), -(^<<), -(>>^), --- Applicative -Applicative (pure), -pass, -ap, -(^$^), -plug, -(^&^), -(^<<^), -(^>>^), --- Monad -Monad, -map', -($!^), -for', -(^&!), -flap', -(^$!), -flor', -(&!^), -ap', -(^$!^), -plug', -(^&!^), --} - + module X, ) where -{- - --- import Control.Applicative (Alternative (empty, (<|>)), Applicative (liftA2, pure, (<*>)), (<**>)) --- import Control.Monad (Monad ((>>=))) --- import Data.Bool (Bool (..), not, (&&), (||)) --- import Data.Foldable (Foldable) --- import Data.Function (const, fix, flip) --- import Data.Functor (Functor (fmap), void) --- import Data.Functor.Compose (Compose (Compose, getCompose)) --- import Data.Functor.Const (Const (Const, getConst)) --- import Data.Functor.Identity (Identity (Identity, runIdentity)) --- import Data.Maybe (Maybe (..)) --- import Data.Traversable (Traversable (sequenceA)) - --- TODO: SIMD: VecCount (..) and VecElem (..) -import GHC.Exts (Constraint, Levity (..), RuntimeRep (..)) -import GHC.Exts qualified as GHC - --------------------------------------------------------------------------------- --- Types - --- | Types with an unlifted alternative. --- --- Laws: --- - @force (lift x) = x@ -class Unlift a where - type U a :: UType - force :: a -> U a - lift :: U a -> a - --------------------------------------------------------------------------------- - -type SKI :: Rep -> Constraint -class SKI r where - _S :: forall (a :: Type r). a -> GHC.Int - --------------------------------------------------------------------------------- - --- TODO: Don't require the objects to be Type r. E.g., functor categories don't --- fit this shape. -type Mor obj r = obj -> obj -> Type r -type Category :: forall obj r. Mor obj r -> Constraint -class Category @obj mor where - identity :: forall (a :: obj). Lev (mor a a) - compose :: forall (a :: obj) (b :: obj) (c :: obj). mor b c -> mor a b -> mor a c - -type CatFunctor :: forall obj0 obj1 r0 r1. (obj0 -> obj1) -> Mor obj0 r0 -> Mor obj1 r1 -> Constraint -class (Category @obj0 mor0, Category @obj1 mor1) => CatFunctor @obj0 @obj1 f mor0 mor1 where - map :: forall (a :: obj0) (b :: obj0). mor0 a b -> mor1 (f a) (f b) - --------------------------------------------------------------------------------- - --- type Hask r = Hask0 r --- type Hask0 r = Mor (Type r) LRep --- type Hask1 k0 r = Mor (k0 -> Type r) LRep --- type Hask2 k0 k1 r = Mor (k0 -> k1 -> Type r) LRep --- type Hask3 k0 k1 k2 r = Mor (k0 -> k1 -> k2 -> Type r) LRep - -newtype Whoa a b = Whoa (forall i j. a i j -> b i j) -instance Category @(k0 -> k1 -> LType) @LRep Whoa where - identity = Whoa \a -> a - compose (Whoa f) (Whoa g) = Whoa \ @i @j a -> f @i @j (g @i @j a) - -newtype Fix2 f i j = Fix2 (f (Fix2 f i j) i j) - --- type --- type Functor f = CatFunctor f (Hask r) (Hask s) - --------------------------------------------------------------------------------- - --- type Functor :: forall r s. (Type r -> Type s) -> Constraint --- class Functor @r f where --- map :: forall (a :: Type r) (b :: Type r). (a -> b) -> f a -> f b - --- type SemiApplicative :: forall r s. (Type r -> Type s) -> Constraint --- class (Functor f) => SemiApplicative @r f where --- map2 :: forall (a :: Type r) (b :: Type r) (c :: Type r). (a -> b -> c) -> f a -> f b -> f c - --- type Applicative :: forall r s. (Type r -> Type s) -> Constraint --- class (SemiApplicative f) => Applicative @r f where --- pure :: forall (a :: Type r). a -> f a - --- type SemiMonad :: forall r s. (Type r -> Type s) -> Constraint --- class (SemiApplicative f) => SemiMonad @r f where --- bind :: forall (a :: Type r) (b :: Type r). (a -> f b) -> f a -> f b - --- type Monad :: forall r s. (Type r -> Type s) -> Constraint --- class (Applicative f, SemiMonad f) => Monad @r f - --- type SemiComonad :: forall r s. - --------------------------------------------------------------------------------- --- Function - --- Note how the associativities and (relative) precedences differ with the --- infix operators in Data.Function. --- infixl 0 &, &! --- infixl 1 $, $! - --- | Function application. --- ($) :: (a -> b) -> a -> b --- f $ x = f x - --- | Strict function application. --- ($!) :: (a -> b) -> a -> b --- f $! !x = f x - --- Flipped function application, or "pipe". --- (&) :: a -> (a -> b) -> b --- x & f = f x - --- Strict flipped function application, or "pipe". --- (&!) :: a -> (a -> b) -> b --- !x &! f = f x - --------------------------------------------------------------------------------- --- Bool - --- class IsBool (bool :: Type r) where --- true :: (Thunked) => bool --- false :: (Thunked) => bool --- bool :: a -> a -> bool -> a - --- instance IsBool Bool where --- true = True --- false = False --- bool t f = \case --- True -> t --- False -> f - --- data UBool :: UType where --- UTrue :: UBool --- UFalse :: UBool - --- instance IsBool UBool where --- true = UTrue --- false = UFalse --- bool t f = \case --- UTrue -> t --- UFalse -> f - --- instance Unlift Bool where --- type U Bool = UBool - --- force True = UTrue --- force False = UFalse - --- lift UTrue = True --- lift UFalse = False - --------------------------------------------------------------------------------- --- Maybe - --- class IsMaybe (maybe :: Type s -> Type r) where --- just :: a -> maybe a --- nothing :: (Thunked) => maybe a --- maybe :: b -> (a -> b) -> maybe a -> b - --- instance IsMaybe Maybe where --- just = Just --- nothing = Nothing --- maybe n j = \case --- Just a -> j a --- Nothing -> n - --- data UMaybe :: LType -> UType where --- UJust :: a -> UMaybe a --- UNothing :: UMaybe a - --- instance IsMaybe UMaybe where --- just = UJust --- nothing = UNothing --- maybe n j = \case --- UJust a -> j a --- UNothing -> n - --- instance Unlift (Maybe a) where --- type U (Maybe a) = UMaybe a - --- force (Just a) = UJust a --- force Nothing = UNothing - --- lift (UJust a) = Just a --- lift UNothing = Nothing - --- data Maybe' :: UType -> LType where --- Just' :: a -> Maybe' a --- Nothing' :: Maybe' a - --- instance IsMaybe Maybe' where --- just = Just' --- nothing = Nothing' --- maybe n j = \case --- Just' a -> j a --- Nothing' -> n - --- data UMaybe' :: UType -> UType where --- UJust' :: a -> UMaybe' a --- UNothing' :: UMaybe' a - --- instance IsMaybe UMaybe' where --- just = UJust' --- nothing = UNothing' --- maybe n j = \case --- UJust' a -> j a --- UNothing' -> n - --- instance Unlift (Maybe' a) where --- type U (Maybe' a) = UMaybe' a - --- force (Just' a) = UJust' a --- force Nothing' = UNothing' - --- lift (UJust' a) = Just' a --- lift UNothing' = Nothing' - --- isJust :: forall s r (maybe :: Type s -> Type r) a. (IsMaybe maybe) => maybe a -> Bool --- isJust = maybe False (const True) - --- isNothing :: (IsMaybe maybe) => maybe a -> Bool --- isNothing = maybe True (const False) - --- type family Maybe# (r :: RuntimeRep) (l :: Levity) :: Type r -> BoxedType l --- type instance Maybe# LRep Lifted = Maybe --- type instance Maybe# URep Lifted = Maybe' --- type instance Maybe# LRep Unlifted = UMaybe --- type instance Maybe# URep Unlifted = UMaybe' - --- type family Lower (a :: Kind) :: Kind where --- Lower (BoxedType l) = TypeU --- Lower (k -> l) = k -> Lower l --- type family X (a :: k) :: Lower k --- type instance X (MaybeL @l) = MaybeL @Unlifted - --------------------------------------------------------------------------------- --- Numeric types - --- TODO - --------------------------------------------------------------------------------- --- Category - --- infixr 9 ∘ - --- infixr 2 <. --- infixl 2 .> - --- (⊲⊳) --- (⋖⋗) --- (⩹⩺) --- (⨟) --- (⦂) --- (⋄) --- (∧∨) --- (⩓⩔) --- (∩∪) --- (=≠≡≢≈≉) --- (<>≤≥≮≯≰≱) --- (≺≻≼≽⊀⊁⋠⋡) --- (⊂⊃⊆⊇⊄⊅⊈⊉) --- (⊏⊐⊑⊒) --- (⊢⊣⊤⊥) --- y = h ∘ g ∘ f ∙^ x --- (f ⦾ g ⦿ x) --- y = h ◁ g ◁ f ◀ x --- y = x ▶ f ▷ g ▷ h --- (⧑⧒⧓⧔⧕⧖⧗⋈⋉⋊) --- (↑↓↔↕↖↗↘↙) --- (⥼⥽⥾⥿) --- (⊰⊱) --- (⭘∘) --- (⦁∙⋅) --- (⊙) --- (⊚) --- (⬬⬭⬮⬯) --- (⬝⬞) --- (⋆) --- (⬥⬦⬧⬨⬩⬪⬫) --- (◖◗) --- (◐◑) --- (⫾) --- (■▪▬▮▰▲▶▼◀◆) --- (∙⋆⋄*≀⌑▫) --- y = x ▪ f ▫ g ▫ h --- y = x ⦂ f ⨟ g ⨟ h - --- TODO: Op, Products, Sums, Clown, Joker - -{- - -type Iso (mor :: obj -> obj -> TypeL) a b = (mor a b, mor b a) -- TODO: use strict pair - -class (Bifunctor f, LDomOf f ~ Hask ρ, RDomOf f ~ Hask ρ) => Monoidal (f :: Type ρ -> Type ρ -> Type ρ) where - type UnitOf f :: Type ρ - unitl :: Iso (Hask ρ) (f (UnitOf f) a) a - unitr :: Iso (Hask ρ) (f a (UnitOf f)) a - assoc :: Iso (Hask ρ) (f (f a b) c) (f a (f b c)) - --- TODO: Having this only work for Hask sucks and is needlessly specialized. --- We can generalize this and some above definitions to any category whose --- objects have kind Type ρ, which isn't just Hask (e.g., Kleisli). -class (Monoidal f) => Cartesian (f :: Type ρ -> Type ρ -> Type ρ) where - fst :: forall (a :: Type ρ) (b :: Type ρ). f a b -> a - snd :: forall (a :: Type ρ) (b :: Type ρ). f a b -> b - - pair :: forall (a :: Type ρ) (b :: Type ρ) (c :: Type ρ). (a -> b) -> (a -> c) -> a -> f b c - pair f g = bimap f g ∘ diag - - diag :: forall (a :: Type ρ). a -> f a a - diag = pair identity identity - --} - --- | Right-to-left composition. --- --- This operator is right associative to exploit laziness in the case where --- the outer function doesn't need its argument: --- --- > (const x <. (f <. g)) y ---> const x ((f <. g) y) ---> x --- --- Note that @f <. g@ is never evaluated. --- (<.) :: (Category v) => v b c -> v a b -> v a c --- (<.) = (.) - --- | Left-to-right composition. --- --- This operator is left associative to exploit laziness in the case where --- the outer function doesn't need its argument: --- --- > ((g .> f) .> const x) y ---> const x ((g .> f) y) ---> x --- --- Note that @g .> f@ is never evaluated. --- (.>) :: (Category v) => v a b -> v b c -> v a c --- (.>) = flip (.) - --- TODO: (.:), (<.:), (.:>) - --------------------------------------------------------------------------------- --- Functor - -{- -infixl 0 ^&, &^, ~^&, ^&~, ~&^, &^~ -infixl 1 $^, ^$, $^~, ~$^, ^$~, ~^$ -infixr 2 <<^, ^>>, ^<<, >>^ - --- | The action of a functor on a function. -map, ($^) :: (Functor f) => (a -> b) -> f a -> f b -map = fmap -($^) = map - --- | The action of a functor on a function, flipped. --- --- With the BlockArguments extension, expressions like "@for xs \\x -> ...@" --- look like for-loops, hence the name "for". -for, (^&) :: (Functor f) => f a -> (a -> b) -> f b -for = flip map -(^&) = for - --- | Application of a function in a functor to a pure value. -flap, (^$) :: (Functor f) => f (a -> b) -> a -> f b -flap f a = f ^& ($ a) -(^$) = flap - --- | Flipped application of a function in a functor to a pure value. -flor, (&^) :: (Functor f) => a -> f (a -> b) -> f b -flor = flip flap -(&^) = flor - -($^~) :: (Functor f, Functor g) => (a -> b) -> g (f a) -> g (f b) -f $^~ a = (f $^) $^ a - -(~^&) :: (Functor f, Functor g) => g (f a) -> (a -> b) -> g (f b) -(~^&) = flip ($^~) - -(~$^) :: (Functor f, Functor g) => g (a -> b) -> f a -> g (f b) -f ~$^ a = f ^& ($^ a) - -(^&~) :: (Functor f, Functor g) => f a -> g (a -> b) -> g (f b) -(^&~) = flip (~$^) - -(^$~) :: (Functor f, Functor g) => f (a -> b) -> g a -> g (f b) -f ^$~ a = (f ^$) $^ a - -(~&^) :: (Functor f, Functor g) => g a -> f (a -> b) -> g (f b) -(~&^) = flip (^$~) - -(~^$) :: (Functor f, Functor g) => g (f (a -> b)) -> a -> g (f b) -f ~^$ a = f ^& (^$ a) - -(&^~) :: (Functor f, Functor g) => a -> g (f (a -> b)) -> g (f b) -(&^~) = flip (~^$) - --- TODO - --- | Right-to-left composition with the first function in a functor. -(<<^) :: (Functor f, Category v) => v b c -> f (v a b) -> f (v a c) -g <<^ f = (g <.) $^ f - --- TODO - --- | Left-to-right composition with the first function in a functor. -(^>>) :: (Functor f, Category v) => f (v a b) -> v b c -> f (v a c) -f ^>> g = f ^& (.> g) - --- TODO - --- | Right-to-left composition with the second function in a functor. -(^<<) :: (Functor f, Category v) => f (v b c) -> v a b -> f (v a c) -g ^<< f = g ^& (<. f) - --- TODO - --- | Left-to-right composition with the second function in a functor. -(>>^) :: (Functor f, Category v) => v a b -> f (v b c) -> f (v a c) -f >>^ g = (f .>) $^ g - --- TODO: *^, ^* - --------------------------------------------------------------------------------- --- Applicative - -infixl 0 ^&^, ~^&^~ -infixl 1 ^$^, ~^$^~ -infixr 2 ^<<^, ^>>^ - --- | Functions with applicative effects. -newtype Appy f a b = Appy {runAppy :: f (a -> b)} - -instance (Functor f) => Functor (Appy f a) where - fmap f (Appy a) = Appy (f $^~ a) - -instance (Applicative f) => Applicative (Appy f a) where - pure = Appy . pure . const - Appy f <*> Appy a = Appy (f ~^$^~ a) - -hom :: (a -> b) -> (b -> b -> c) -> a -> a -> c -hom f g x y = g (f x) (f y) - -instance (Alternative f) => Alternative (Appy f a) where - empty = Appy empty - --- Appy x <|> Appy y = Appy (x <|> y) --- (<|>) = hom runAppy (<|>) - -instance (Applicative f) => Category (Appy f) where - id = Appy (pure id) - Appy f . Appy g = Appy ((.) $^ f ^$^ g) - --- TODO: Remove ap and plug? --- TODO: liftA{,1,2,3,4} - --- | An alias for @pure ()@. -pass :: (Applicative f) => f () -pass = pure () - --- | Application in an applicative functor. -ap, (^$^) :: (Applicative f) => f (a -> b) -> f a -> f b -ap = (<*>) -(^$^) = ap - --- | Flipped application in an applicative functor (with effects resolved as --- they appear, left-to-right). -plug, (^&^) :: (Applicative f) => f a -> f (a -> b) -> f b -plug = (<**>) -(^&^) = plug - -(~^$^~) :: (Applicative f, Applicative g) => g (f (a -> b)) -> g (f a) -> g (f b) -f ~^$^~ a = (^$^) $^ f ^$^ a - -(~^&^~) :: (Applicative f, Applicative g) => g (f a) -> g (f (a -> b)) -> g (f b) -f ~^&^~ a = (^&^) $^ f ^$^ a - --- TODO: document -(^<<^) :: (Applicative f, Category v) => f (v b c) -> f (v a b) -> f (v a c) -(^<<^) = liftA2 (<.) - --- TODO: document -(^>>^) :: (Applicative f, Category v) => f (v a b) -> f (v b c) -> f (v a c) -(^>>^) = liftA2 (.>) - --- TODO: "semicolons" - --------------------------------------------------------------------------------- --- Monad - -infixl 0 ^&!, &!^, ^&!^ -infixl 1 $!^, ^$!, ^$!^ - -map', ($!^) :: (Monad m) => (a -> b) -> m a -> m b -map' f mx = mx >>= \x -> pure $! f x -($!^) = map' - -for', (^&!) :: (Monad m) => m a -> (a -> b) -> m b -for' = flip map' -(^&!) = for - -flap', (^$!) :: (Monad m) => m (a -> b) -> a -> m b -flap' mf x = mf >>= \f -> pure $! f x -(^$!) = flap' - -flor', (&!^) :: (Monad m) => a -> m (a -> b) -> m b -flor' = flip flap' -(&!^) = flor' - -ap', (^$!^) :: (Monad m) => m (a -> b) -> m a -> m b -ap' mf mx = do - f <- mf - x <- mx - pure $! f x -(^$!^) = ap' - -plug', (^&!^) :: (Monad m) => m a -> m (a -> b) -> m b -plug' mx mf = do - x <- mx - f <- mf - pure $! f x -(^&!^) = plug' --} - --- (.) :: (b0 -> c) -> (a0 -> b0) -> (a0 -> c) --- (g . f) a0 = g (f a0) --- (^.) :: (b0 -> b1 -> c) -> (a0 -> b1) -> (b0 -> a0 -> c) --- (g ^. f) b0 a0 = g b0 (f a0) --- (^^.) :: (b0 -> b1 -> b2 -> c) -> (a0 -> b2) -> (b0 -> b1 -> a0 -> c) --- (g ^^. f) b0 b1 a0 = g b0 b1 (f a0) --- (^^^.) :: (b0 -> b1 -> b2 -> b3 -> c) -> (a0 -> b3) -> (b0 -> b1 -> b2 -> a0 -> c) --- (g ^^^. f) b0 b1 b2 a0 = g b0 b1 b2 (f a0) --- (.^) :: (b0 -> c) -> (a0 -> a1 -> b0) -> (a0 -> a1 -> c) --- (g .^ f) a0 a1 = g (f a0 a1) --- (^.^) :: (b0 -> b1 -> c) -> (a0 -> a1 -> b1) -> (b0 -> a0 -> a1 -> c) --- (g ^.^ f) b0 a0 a1 = g b0 (f a0 a1) --- (^^.^) :: (b0 -> b1 -> b2 -> c) -> (a0 -> a1 -> b2) -> (b0 -> b1 -> a0 -> a1 -> c) --- (g ^^.^ f) b0 b1 a0 a1 = g b0 b1 (f a0 a1) --- (^^^.^) :: (b0 -> b1 -> b2 -> b3 -> c) -> (a0 -> a1 -> b3) -> (b0 -> b1 -> b2 -> a0 -> a1 -> c) --- (g ^^^.^ f) b0 b1 b2 a0 a1 = g b0 b1 b2 (f a0 a1) --- (.^^) :: (b0 -> c) -> (a0 -> a1 -> a2 -> b0) -> (a0 -> a1 -> a2 -> c) --- (^.^^) :: (b0 -> b1 -> c) -> (a0 -> a1 -> a2 -> b1) -> (b0 -> a0 -> a1 -> a2 -> c) --- (^^.^^) :: (b0 -> b1 -> b2 -> c) -> (a0 -> a1 -> a2 -> b2) -> (b0 -> b1 -> a0 -> a1 -> a2 -> c) --- (^^^.^^) :: (b0 -> b1 -> b2 -> b3 -> c) -> (a0 -> a1 -> a2 -> b3) -> (b0 -> b1 -> b2 -> a0 -> a1 -> a2 -> c) --- (.^^^) :: (b0 -> c) -> (a0 -> a1 -> a2 -> a3 -> b0) -> (a0 -> a1 -> a2 -> a3 -> c) --- (^.^^^) :: (b0 -> b1 -> c) -> (a0 -> a1 -> a2 -> a3 -> b1) -> (b0 -> a0 -> a1 -> a2 -> a3 -> c) --- (^^.^^^) :: (b0 -> b1 -> b2 -> c) -> (a0 -> a1 -> a2 -> a3 -> b2) -> (b0 -> b1 -> a0 -> a1 -> a2 -> a3 -> c) --- (^^^.^^^) :: (b0 -> b1 -> b2 -> b3 -> c) -> (a0 -> a1 -> a2 -> a3 -> b3) -> (b0 -> b1 -> b2 -> a0 -> a1 -> a2 -> a3 -> c) - --} +import Lude.Algebra as X +import Lude.Bool as X +import Lude.Constraint as X +import Lude.Function as X +import Lude.Haskell as X +import Lude.List as X +import Lude.Unit as X +import Lude.Void as X diff --git a/src/Lude/Algebra.hs b/src/Lude/Algebra.hs @@ -0,0 +1,5 @@ +module Lude.Algebra ( + module X, +) where + +import Lude.Algebra.Category as X diff --git a/src/Lude/Algebra/Algebra.hs b/src/Lude/Algebra/Algebra.hs @@ -1,80 +0,0 @@ -module Lude.Algebra.Algebra ( - Algebra, - Algebraic, - -- - DefaultRecursive (..), - Recursive (..), - -- - Coalgebra, - Coalgebraic, - -- - DefaultCorecursive (..), - Corecursive (..), -) where - -import Lude.Algebra.Category -import Lude.Haskell - --- TODO: Check whether we really need a separate default instance for Nt. --- I think it's necessary, because composition with `map h` forces eager --- evaluation of h. - --- TODO: Add Coalgebraic (Algebraic) as a super class of Recursive (Corecursive). - --------------------------------------------------------------------------------- - --- | An algebra for an endofunctor. -type Algebra :: forall {k}. Cat k -> Endo k -> k -> Type -type Algebra p f a = f a `p` a - --- | A type equipped with an algebra for an endofunctor. -type Algebraic :: forall {k}. Cat k -> Endo k -> k -> Constraint -class (EndofunctorialOn p f) => Algebraic p f a | a -> f where - wrap :: Algebra p f a - --------------------------------------------------------------------------------- - -type DefaultRecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint -class DefaultRecursive p f r where - defaultCata :: (Algebraic p f r) => forall a. Algebra p f a -> r `p` a - -instance (Coalgebraic Function f r) => DefaultRecursive Function f r where - defaultCata f = h where h = f . map h . peel -instance (Categorical p, Categorical q, Coalgebraic (p ==> q) f r) => DefaultRecursive (NT p q) f r where - defaultCata f@(Natural _) = h where h = Natural (comp f . comp (map h) . comp peel) \\ witnessMor (wrap @(p ==> q) @f @r) - --- | A type equipped with an initial algebra for an endofunctor. -type Recursive :: forall {k}. Cat k -> Endo k -> k -> Constraint -class (Algebraic p f r) => Recursive p f r where - cata :: forall a. Algebra p f a -> r `p` a - default cata :: (DefaultRecursive p f r) => forall a. Algebra p f a -> r `p` a - cata = defaultCata - --------------------------------------------------------------------------------- - --- | A coalgebra for an endofunctor. -type Coalgebra :: forall {k}. Cat k -> Endo k -> k -> Type -type Coalgebra p g b = b `p` g b - --- | A type equipped with a coalgebra for an endofunctor. -type Coalgebraic :: forall {k}. Cat k -> Endo k -> k -> Constraint -class (EndofunctorialOn p g) => Coalgebraic p g b | b -> g where - peel :: Coalgebra p g b - --------------------------------------------------------------------------------- - -type DefaultCorecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint -class DefaultCorecursive p g s where - defaultAna :: (Coalgebraic p g s) => forall b. Coalgebra p g b -> b `p` s - -instance (Algebraic Function g s) => DefaultCorecursive Function g s where - defaultAna g = h where h = wrap . map h . g -instance (Categorical p, Categorical q, Algebraic (p ==> q) g s) => DefaultCorecursive (p ==> q) g s where - defaultAna g@(Natural _) = h where h = Natural (comp wrap . comp (map h) . comp g) \\ witnessMor (peel @(p ==> q) @g @s) - --- | A type equipped with a final coalgebra for an endofunctor. -type Corecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint -class (Coalgebraic p g s) => Corecursive p g s where - ana :: forall b. Coalgebra p g b -> b `p` s - default ana :: (DefaultCorecursive p g s) => forall b. Coalgebra p g b -> b `p` s - ana = defaultAna diff --git a/src/Lude/Algebra/Category.hs b/src/Lude/Algebra/Category.hs @@ -2,6 +2,8 @@ module Lude.Algebra.Category ( module X, ) where +import Lude.Algebra.Category.Adjunction as X +import Lude.Algebra.Category.Algebra as X import Lude.Algebra.Category.Bifunctor as X import Lude.Algebra.Category.Constrained as X import Lude.Algebra.Category.Core as X @@ -16,10 +18,6 @@ import Lude.Algebra.Category.Terminal as X -- TODO: Free and cofree --- TODO: Adjunctions and zap - --- TODO: Eilenberg-Moore (co)algebras? - -- TODO: Profunctors? Other special kinds of functors, given distinct names? -- That would allow being a functor in multiple ways without losing coherence. -- E.g., lists could be mappable "normally" and filterable (choose is map). diff --git a/src/Lude/Algebra/Category/Adjunction.hs b/src/Lude/Algebra/Category/Adjunction.hs @@ -6,6 +6,8 @@ import Lude.Algebra.Category.Core import Lude.Algebra.Category.Iso import Lude.Haskell +-- TODO: Zappable? + -------------------------------------------------------------------------------- type Adjoint :: forall {i} {j}. (i -> j) -> (j -> i) -> Constraint diff --git a/src/Lude/Algebra/Category/Algebra.hs b/src/Lude/Algebra/Category/Algebra.hs @@ -0,0 +1,82 @@ +module Lude.Algebra.Category.Algebra ( + Algebra, + Algebraic, + -- + DefaultRecursive (..), + Recursive (..), + -- + Coalgebra, + Coalgebraic, + -- + DefaultCorecursive (..), + Corecursive (..), +) where + +import Lude.Algebra.Category.Core +import Lude.Haskell + +-- TODO: Check whether we really need a separate default instance for Nt. +-- I think it's necessary, because composition with `map h` forces eager +-- evaluation of h. + +-- TODO: Add Coalgebraic (Algebraic) as a super class of Recursive (Corecursive). + +-- TODO: Eilenberg-Moore (co)algebras? + +-------------------------------------------------------------------------------- + +-- | An algebra for an endofunctor. +type Algebra :: forall {k}. Cat k -> Endo k -> k -> Type +type Algebra p f a = f a `p` a + +-- | A type equipped with an algebra for an endofunctor. +type Algebraic :: forall {k}. Cat k -> Endo k -> k -> Constraint +class (EndofunctorialOn p f) => Algebraic p f a | a -> f where + wrap :: Algebra p f a + +-------------------------------------------------------------------------------- + +type DefaultRecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint +class DefaultRecursive p f r where + defaultCata :: (Algebraic p f r) => forall a. Algebra p f a -> r `p` a + +instance (Coalgebraic Function f r) => DefaultRecursive Function f r where + defaultCata f = h where h = f . map h . peel +instance (Categorical p, Categorical q, Coalgebraic (p ==> q) f r) => DefaultRecursive (NT p q) f r where + defaultCata f@(Natural _) = h where h = Natural (comp f . comp (map h) . comp peel) \\ witnessMor (wrap @(p ==> q) @f @r) + +-- | A type equipped with an initial algebra for an endofunctor. +type Recursive :: forall {k}. Cat k -> Endo k -> k -> Constraint +class (Algebraic p f r) => Recursive p f r where + cata :: forall a. Algebra p f a -> r `p` a + default cata :: (DefaultRecursive p f r) => forall a. Algebra p f a -> r `p` a + cata = defaultCata + +-------------------------------------------------------------------------------- + +-- | A coalgebra for an endofunctor. +type Coalgebra :: forall {k}. Cat k -> Endo k -> k -> Type +type Coalgebra p g b = b `p` g b + +-- | A type equipped with a coalgebra for an endofunctor. +type Coalgebraic :: forall {k}. Cat k -> Endo k -> k -> Constraint +class (EndofunctorialOn p g) => Coalgebraic p g b | b -> g where + peel :: Coalgebra p g b + +-------------------------------------------------------------------------------- + +type DefaultCorecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint +class DefaultCorecursive p g s where + defaultAna :: (Coalgebraic p g s) => forall b. Coalgebra p g b -> b `p` s + +instance (Algebraic Function g s) => DefaultCorecursive Function g s where + defaultAna g = h where h = wrap . map h . g +instance (Categorical p, Categorical q, Algebraic (p ==> q) g s) => DefaultCorecursive (p ==> q) g s where + defaultAna g@(Natural _) = h where h = Natural (comp wrap . comp (map h) . comp g) \\ witnessMor (peel @(p ==> q) @g @s) + +-- | A type equipped with a final coalgebra for an endofunctor. +type Corecursive :: forall {k}. Cat k -> Endo k -> k -> Constraint +class (Coalgebraic p g s) => Corecursive p g s where + ana :: forall b. Coalgebra p g b -> b `p` s + default ana :: (DefaultCorecursive p g s) => forall b. Coalgebra p g b -> b `p` s + ana = defaultAna diff --git a/src/Lude/Algebra/Category/Core.hs b/src/Lude/Algebra/Category/Core.hs @@ -130,6 +130,8 @@ instance (FunctorialOn p p f) => EndofunctorialOn p f type ObjArg :: forall {i} {j}. (i -> j) -> Predicate i type ObjArg f = Obj (Dom f) +-- for :: forall {i} {j} (f :: i -> j) (a :: i) (b :: i). (Functorial f) => Dom f i j -> Cod f (f i) (f j) + preservesObj :: forall {i} {j} (p :: Cat i) (q :: Cat j). forall (f :: i -> j) -> (FunctorialOn p q f) => forall (a :: i) -> Obj p a :- Obj q (f a) preservesObj _ _ = preservesObj_ diff --git a/src/Lude/Function.hs b/src/Lude/Function.hs @@ -0,0 +1,12 @@ +module Lude.Function ( + flip, + const, + ($), + (&), +) where + +import Data.Function + +-- TODO: Generalize some of this? E.g., for CCCs? + +--------------------------------------------------------------------------------