lude

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

commit bc2229ec25c50ef3c3a4d73dbd3c301e6eca4b60
parent 9400c550dc27c17893c1e454cef9c1d7b7089e61
Author: Robert Russell <robert@rr3.xyz>
Date:   Wed, 16 Sep 2026 16:44:01 -0700

Function: add Repr-polymorphic combinators

Diffstat:
MTodo/Lude.hs | 40----------------------------------------
Msrc/Lude.hs | 3++-
Msrc/Lude/Algebra/Category/Core.hs | 6+++---
Msrc/Lude/Function.hs | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/Lude/Haskell/Category.hs | 19++++++++++++-------
Msrc/Lude/Haskell/Functional.hs | 8++++----
6 files changed, 154 insertions(+), 58 deletions(-)

diff --git a/Todo/Lude.hs b/Todo/Lude.hs @@ -108,44 +108,6 @@ class Unlift a where -------------------------------------------------------------------------------- -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 @@ -366,8 +328,6 @@ newtype Fix2 f i j = Fix2 (f (Fix2 f i j) i j) {- -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 diff --git a/src/Lude.hs b/src/Lude.hs @@ -5,7 +5,8 @@ module Lude ( import Lude.Algebra as X import Lude.Bool as X import Lude.Constraint as X -import Lude.Function as X +import Lude.Equivalence as X +import Lude.Function as X hiding ((.)) import Lude.Haskell as X import Lude.IO as X import Lude.List as X diff --git a/src/Lude/Algebra/Category/Core.hs b/src/Lude/Algebra/Category/Core.hs @@ -199,16 +199,16 @@ instance (Categorical p, Categorical q) => Functorial (NT p q) where -------------------------------------------------------------------------------- -- Haskell -instance Categorical Function where +instance forall (r :: Repr). (Functional# r) => Categorical (Function @r) where identity = identityFunction compose = composeFunction -instance Functorial (Function a) where +instance forall (r :: Repr) (a :: Type @r). (Functional# r) => Functorial (Function @r a) where type Dom (Function a) = Function type Cod (Function a) = Function map = compose -instance Functorial Function where +instance forall (r :: Repr). (Functional# r) => Functorial (Function @r) where type Dom Function = Dual Function type Cod Function = Function ==> Function map (MkDual f) = Naturally (. f) diff --git a/src/Lude/Function.hs b/src/Lude/Function.hs @@ -1,13 +1,143 @@ module Lude.Function ( + identity, + app, + ($), + rapp, + (&), const, flip, on, - ($), - (&), + compose00, + (.), + compose01, + (.*), + compose10, + (*.), + compose11, + (*.*), ) where -import Data.Function (const, flip, on, ($), (&)) +import Data.Function (($)) + +import Lude.Algebra.Category.Core (identity) +import Lude.Haskell -- TODO: Generalize some of this? E.g., for CCCs? +-- TODO: How should we deal with the (.) naming conflict with category? + +-- TODO: Repr-generic S and Phi combinators? + -------------------------------------------------------------------------------- + +app :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s). (a -> b) -> (a -> b) +app = ($) +{-# INLINE app #-} + +rapp, (&) :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s). (Functional# r) => a -> (a -> b) -> b +rapp = lam# \x f -> app# f x +(&) = rapp +{-# INLINE rapp #-} +{-# INLINE (&) #-} + +const + :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s) + . (Functional# r, Functional# s) => a -> (b -> a) +const = lam2# \x _ -> x +{-# INLINE const #-} + +flip + :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r, Functional# s) => (a -> b -> c) -> (b -> a -> c) +flip f = lam2# \y x -> app2# f x y +{-# INLINE flip #-} + +on + :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r, Functional# s) => (b -> b -> c) -> (a -> b) -> (a -> a -> c) +on f g = lam2# \x y -> app2# f (app# g x) (app# g y) +{-# INLINE on #-} + +-------------------------------------------------------------------------------- +-- Composition + +compose00, + (.) + :: forall {r0 :: Repr} (a0 :: Type @r0) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r0, Functional# s) => (b -> c) -> (a0 -> b) -> (a0 -> c) +compose00 = composeFunction +(.) = compose00 +{-# INLINE compose00 #-} +{-# INLINE (.) #-} + +compose01, + (.*) + :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r0, Functional# r1, Functional# s) => (b -> c) -> (a0 -> a1 -> b) -> (a0 -> a1 -> c) +compose01 g f = lam# \x0 -> compose00 g (f `app#` x0) +(.*) = compose01 +{-# INLINE compose01 #-} +{-# INLINE (.*) #-} + +compose10, + (*.) + :: forall {r0 :: Repr} (a0 :: Type @r0) {s0 :: Repr} (b0 :: Type @s0) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r0, Functional# s0, Functional# s) => (b0 -> b -> c) -> (a0 -> b) -> (b0 -> a0 -> c) +compose10 g f = lam# \y -> compose00 (g `app#` y) f +(*.) = compose10 +{-# INLINE compose10 #-} +{-# INLINE (*.) #-} + +compose11, + (*.*) + :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {s0 :: Repr} (b0 :: Type @s0) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r0, Functional# r1, Functional# s0, Functional# s) => (b0 -> b -> c) -> (a0 -> a1 -> b) -> (b0 -> a0 -> a1 -> c) +compose11 g f = lam# \y -> compose01 (g `app#` y) f +(*.*) = compose11 +{-# INLINE compose11 #-} +{-# INLINE (*.*) #-} + +-- compose02, +-- (.**) +-- :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {r2 :: Repr} (a2 :: Type @r2) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) +-- . (Functional# r0, Functional# r1, Functional# r2, Functional# s) => (b -> c) -> (a0 -> a1 -> a2 -> b) -> (a0 -> a1 -> a2 -> c) +-- compose02 g f = lam# \x -> compose01 g (f `app#` x) +-- (.**) = compose02 +-- {-# INLINE compose02 #-} +-- {-# INLINE (.**) #-} + +-- compose12, +-- (*.**) +-- :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {r2 :: Repr} (a2 :: Type @r2) {s0 :: Repr} (b0 :: Type @s0) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) +-- . (Functional# r0, Functional# r1, Functional# r2, Functional# s0, Functional# s) => (b0 -> b -> c) -> (a0 -> a1 -> a2 -> b) -> (b0 -> a0 -> a1 -> a2 -> c) +-- compose12 g f = lam# \y -> compose02 (g `app#` y) f +-- (*.**) = compose12 +-- {-# INLINE compose12 #-} +-- {-# INLINE (*.**) #-} + +-- compose20, +-- (**.) +-- :: forall {r0 :: Repr} (a0 :: Type @r0) {s0 :: Repr} (b0 :: Type @s0) {s1 :: Repr} (b1 :: Type @s1) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) +-- . (Functional# r0, Functional# s0, Functional# s1, Functional# s) => (b0 -> b1 -> b -> c) -> (a0 -> b) -> (b0 -> b1 -> a0 -> c) +-- compose20 g f = lam# \y -> compose10 (g `app#` y) f +-- (**.) = compose20 +-- {-# INLINE compose20 #-} +-- {-# INLINE (**.) #-} + +-- compose21, +-- (**.*) +-- :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {s0 :: Repr} (b0 :: Type @s0) {s1 :: Repr} (b1 :: Type @s1) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) +-- . (Functional# r0, Functional# r1, Functional# s0, Functional# s1, Functional# s) => (b0 -> b1 -> b -> c) -> (a0 -> a1 -> b) -> (b0 -> b1 -> a0 -> a1 -> c) +-- compose21 g f = lam# \y -> compose11 (g `app#` y) f +-- (**.*) = compose21 +-- {-# INLINE compose21 #-} +-- {-# INLINE (**.*) #-} + +-- compose22, +-- (**.**) +-- :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {r2 :: Repr} (a2 :: Type @r2) {s0 :: Repr} (b0 :: Type @s0) {s1 :: Repr} (b1 :: Type @s1) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) +-- . (Functional# r0, Functional# r1, Functional# r2, Functional# s0, Functional# s1, Functional# s) => (b0 -> b1 -> b -> c) -> (a0 -> a1 -> a2 -> b) -> (b0 -> b1 -> a0 -> a1 -> a2 -> c) +-- compose22 g f = lam# \y -> compose12 (g `app#` y) f +-- (**.**) = compose22 +-- {-# INLINE compose22 #-} +-- {-# INLINE (**.**) #-} diff --git a/src/Lude/Haskell/Category.hs b/src/Lude/Haskell/Category.hs @@ -51,10 +51,11 @@ module Lude.Haskell.Category ( ) where import GHC.Exts qualified as GHC -import Prelude qualified as Base import Lude.Haskell.Constraint +import Lude.Haskell.Functional import Lude.Haskell.Kind +import Lude.Haskell.Repr import Lude.Haskell.Type -- NOTE: `Entailment`/`:-` is to `Constraint` what `Function`/`->` is to `Type`. @@ -72,8 +73,8 @@ type Cat :: Kind -> Kind type Cat i = i -> i -> Type -- | Functions between two types (which form a category) -type Function :: Cat Type -type Function = (->) +type Function :: forall (r :: Repr). Cat (Type @r) +type Function @r = (->) -- | Natural transformations to `Function`/`->` type (~>) :: forall i r. Cat (i -> Type @r) @@ -83,11 +84,15 @@ type f ~> g = forall x. f x -> g x type (~~>) :: forall i j r. Cat (i -> j -> Type @r) type f ~~> g = forall x y. f x y -> g x y -identityFunction :: forall a. a -> a -identityFunction = Base.id +identityFunction :: forall {r :: Repr} (a :: Type @r). (Functional# r) => a -> a +identityFunction = lam# \x -> x +{-# INLINE identityFunction #-} -composeFunction :: forall a b c. (b -> c) -> (a -> b) -> (a -> c) -composeFunction = (Base..) +composeFunction + :: forall {r :: Repr} (a :: Type @r) {s :: Repr} (b :: Type @s) {t :: Repr} (c :: Type @t) + . (Functional# r, Functional# s) => (b -> c) -> (a -> b) -> (a -> c) +composeFunction f g = lam# \x -> f `app#` (g `app#` x) +{-# INLINE composeFunction #-} -- | Entailments between two constraints (which form a category) type Entailment :: Cat Constraint diff --git a/src/Lude/Haskell/Functional.hs b/src/Lude/Haskell/Functional.hs @@ -31,13 +31,13 @@ class Functional# r where app# :: forall (a :: Type @r) {s} (b :: Type @s). (a -> b) -> (Lev a -> b) lam2# - :: forall {r :: Repr} (a :: Type @r) (b :: Type @r) {s} (c :: Type @s) - . (Functional# r) => (Lev a -> Lev b -> c) -> (a -> b -> c) + :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {s} (b :: Type @s) + . (Functional# r0, Functional# r1) => (Lev a0 -> Lev a1 -> b) -> (a0 -> a1 -> b) lam2# f = lam# \x -> lam# (f x) app2# - :: forall {r :: Repr} (a :: Type @r) (b :: Type @r) {s} (c :: Type @s) - . (Functional# r) => (a -> b -> c) -> (Lev a -> Lev b -> c) + :: forall {r0 :: Repr} (a0 :: Type @r0) {r1 :: Repr} (a1 :: Type @r1) {s} (b :: Type @s) + . (Functional# r0, Functional# r1) => (a0 -> a1 -> b) -> (Lev a0 -> Lev a1 -> b) app2# f x y = f `app#` x `app#` y --------------------------------------------------------------------------------