lude

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

commit 375ae8f19c95cb47bd5133660135ed952e8e7f93
parent 6d41b7f3f1653a2c17a9b7e4bea1ea2e26d959cd
Author: Robert Russell <robert@rr3.xyz>
Date:   Wed, 16 Sep 2026 10:52:15 -0700

Haskell: add Functional# class for representation-genericity

Diffstat:
Msrc/Lude/Haskell.hs | 1+
Asrc/Lude/Haskell/Functional.hs | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Lude/Haskell/Kind.hs | 8++++++--
Msrc/Lude/Haskell/Type.hs | 12------------
4 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/src/Lude/Haskell.hs b/src/Lude/Haskell.hs @@ -7,6 +7,7 @@ import GHC.Exts as X (IsList (..), IsString (..)) import Lude.Haskell.Category as X -- TODO: Probably hide some stuff from here. import Lude.Haskell.Constraint as X import Lude.Haskell.Equality as X +import Lude.Haskell.Functional as X import Lude.Haskell.Kind as X import Lude.Haskell.Repr as X (Repr) import Lude.Haskell.Type as X diff --git a/src/Lude/Haskell/Functional.hs b/src/Lude/Haskell/Functional.hs @@ -0,0 +1,61 @@ +module Lude.Haskell.Functional ( + Lev, + Functional# (..), + lam2#, + app2#, +) where + +import Data.Tuple.Experimental qualified as GHC + +import Lude.Haskell.Constraint +import Lude.Haskell.Repr +import Lude.Haskell.Repr qualified as Repr +import Lude.Haskell.Type + +-------------------------------------------------------------------------------- + +-- | Transparently box a type of any representation +-- +-- Use `Lev` to declare unlifted values at the top-level. For example, for any +-- @r :: Repr@, @A :: Type r@, and @bar :: A@: +-- @ +-- foo :: Lev A +-- foo = bar +-- @ +type Lev :: forall {r}. Type @r -> Type +type Lev a = (GHC.CTuple0) => a + +type Functional# :: Repr -> Constraint +class Functional# r where + lam# :: forall (a :: Type @r) {s} (b :: Type @s). (Lev a -> b) -> (a -> b) + 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) +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) +app2# f x y = f `app#` x `app#` y + +-------------------------------------------------------------------------------- + +instance Functional# Repr.BoxL where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.BoxU where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Addr where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Int where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Int8 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Int16 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Int32 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Int64 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Nat where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Nat8 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Nat16 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Nat32 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Nat64 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Flt32 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} +instance Functional# Repr.Flt64 where lam# f = \x -> f x; {-# INLINE lam# #-}; app# f = \x -> f x; {-# INLINE app# #-} + +-- TODO: Tuple and Sum instances? There're infinitely many :( diff --git a/src/Lude/Haskell/Kind.hs b/src/Lude/Haskell/Kind.hs @@ -14,12 +14,16 @@ import Lude.Haskell.Repr qualified as Repr type Kind = GHC.TYPE Repr.BoxL +-- NOTE: We typically avoid conflating types and kinds, +-- but when we do conflate them, we use KindOrType. +type KindOrType r = GHC.TYPE r + -- | The kind of "invisibly" `Repr`-generic types and constraints type KindR :: Kind type KindR = forall (r :: Repr). Kind -type Endo :: Kind -> Kind +type Endo :: forall (r :: Repr). KindOrType r -> Kind type Endo i = i -> i -type Biendo :: Kind -> Kind +type Biendo :: forall (r :: Repr). KindOrType r -> Kind type Biendo i = i -> i -> i diff --git a/src/Lude/Haskell/Type.hs b/src/Lude/Haskell/Type.hs @@ -1,7 +1,6 @@ module Lude.Haskell.Type ( Type, Type1, - Lev, Tuple#, Tuple, ) where @@ -21,17 +20,6 @@ type Type @r = GHC.TYPE r type Type1 :: Kind -> KindR type Type1 i @r = i -> Type @r --- | Transparently box a type of any representation --- --- Use `Lev` to declare unlifted values at the top-level. For example, for any --- @r :: Repr@, @A :: Type r@, and @bar :: A@: --- @ --- foo :: Lev A --- foo = bar --- @ -type Lev :: forall {r}. Type @r -> Type -type Lev a = (GHC.CTuple0) => a - -------------------------------------------------------------------------------- -- Tuples