packages feed

singleraeh-0.3.0: src/Singleraeh/Tuple.hs

module Singleraeh.Tuple where

import Singleraeh.Demote
import Data.Kind ( Type, Constraint )

data SUnit (unit :: ()) where SUnit :: SUnit '()

demoteSUnit :: SUnit unit -> ()
demoteSUnit SUnit = ()

instance Demotable SUnit where
    type Demote SUnit = ()
    demote = demoteSUnit

type STuple2 :: (a -> Type) -> (b -> Type) -> (a, b) -> Type
data STuple2 sa sb ab where
    STuple2 :: sa a -> sb b -> STuple2 sa sb '(a, b)

demoteSTuple2
    :: forall da db sa sb ab
    .  (forall a. sa a -> da)
    -> (forall b. sb b -> db)
    -> STuple2 sa sb ab
    -> (da, db)
demoteSTuple2 demoteSA demoteSB (STuple2 sa sb) = (demoteSA sa, demoteSB sb)

instance (Demotable sa, Demotable sb) => Demotable (STuple2 sa sb) where
    type Demote (STuple2 sa sb) = (Demote sa, Demote sb)
    demote = demoteSTuple2 demote demote

class SingTuple2 (cl :: lk -> Constraint) (cr :: rk -> Constraint) (sl :: lk -> Type) (sr :: rk -> Type) (lr :: (lk, rk)) where
    singTuple2'
        :: (forall l. cl l => sl l)
        -> (forall r. cr r => sr r)
        -> STuple2 sl sr lr

singTuple2
    :: forall cl cr sl sr lr. SingTuple2 cl cr sl sr lr
    => (forall l. cl l => sl l)
    -> (forall r. cr r => sr r)
    -> STuple2 sl sr lr
singTuple2 = singTuple2' @_ @_ @cl @cr

instance (cl l, cr r) => SingTuple2 cl cr sl sr '(l, r) where
    singTuple2' sl sr = STuple2 sl sr

type STuple3 :: (a -> Type) -> (b -> Type) -> (c -> Type) -> (a, b, c) -> Type
data STuple3 sa sb sc abc where
    STuple3 :: sa a -> sb b -> sc c -> STuple3 sa sb sc '(a, b, c)

demoteSTuple3
    :: forall da db dc sa sb sc abc
    .  (forall a. sa a -> da)
    -> (forall b. sb b -> db)
    -> (forall c. sc c -> dc)
    -> STuple3 sa sb sc abc
    -> (da, db, dc)
demoteSTuple3 demoteSA demoteSB demoteSC (STuple3 sa sb sc) =
    (demoteSA sa, demoteSB sb, demoteSC sc)

instance (Demotable sa, Demotable sb, Demotable sc)
  => Demotable (STuple3 sa sb sc) where
    type Demote (STuple3 sa sb sc) = (Demote sa, Demote sb, Demote sc)
    demote = demoteSTuple3 demote demote demote

class SingTuple3 (ca :: ak -> Constraint) (cb :: bk -> Constraint) (cc :: ck -> Constraint) (sa :: ak -> Type) (sb :: bk -> Type) (sc :: ck -> Type) (abc :: (ak, bk, ck)) where
    singTuple3'
        :: (forall a. ca a => sa a)
        -> (forall b. cb b => sb b)
        -> (forall c. cc c => sc c)
        -> STuple3 sa sb sc abc

singTuple3
    :: forall ca cb cc sa sb sc abc. SingTuple3 ca cb cc sa sb sc abc
    => (forall a. ca a => sa a)
    -> (forall b. cb b => sb b)
    -> (forall c. cc c => sc c)
    -> STuple3 sa sb sc abc
singTuple3 = singTuple3' @_ @_ @_ @ca @cb @cc

instance (ca a, cb b, cc c) => SingTuple3 ca cb cc sa sb sc '(a, b, c) where
    singTuple3' sa sb sc = STuple3 sa sb sc