packages feed

singleraeh-0.2.1: src/Singleraeh/List.hs

{-# LANGUAGE UndecidableInstances #-}

module Singleraeh.List where

import Data.Kind ( Type )
import Singleraeh.Demote

-- | Singleton list.
type SList :: (a -> Type) -> [a] -> Type
data SList sa as where
    SCons :: sa a -> SList sa as -> SList sa (a : as)
    SNil  ::                        SList sa '[]

demoteSList
    :: forall da sa as
    .  (forall a. sa a -> da)
    -> SList sa as
    -> [da]
demoteSList demoteSA = \case
  SCons sa sas -> demoteSA sa : demoteSList demoteSA sas
  SNil         -> []

instance Demotable sa => Demotable (SList sa) where
    type Demote (SList sa) = [Demote sa]
    demote = demoteSList demote

-- | Reverse a type level list.
type Reverse as = Reverse' '[] as
type family Reverse' (acc :: [k]) (as :: [k]) :: [k] where
  Reverse' acc (a : as) = Reverse' (a : acc) as
  Reverse' acc '[]      = acc

sReverse :: SList sa as -> SList sa (Reverse as)
sReverse as = sReverse' SNil as

sReverse' :: SList sa acc -> SList sa as -> SList sa (Reverse' acc as)
sReverse' acc = \case
  SCons a as -> sReverse' (SCons a acc) as
  SNil       -> acc