packages feed

poly-rec-0.7.0.4: src/Data/HList.hs

{-|
Module      : Data.HList
Description :
Implementation of strongly typed heterogeneous lists.
Copyright   : (c) Juan García Garland, 2018,2023
License     : GPL
Maintainer  : jpgarcia@fing.edu.uy
Stability   : experimental
Portability : POSIX
|-}

{-# OPTIONS_GHC -fno-warn-missing-methods,
                -fno-warn-partial-type-signatures #-}

{-# LANGUAGE DataKinds,
             TypeOperators,
             PolyKinds,
             GADTs,
             TypeInType,
             RankNTypes,
             StandaloneDeriving,
             FlexibleInstances,
             FlexibleContexts,
             ConstraintKinds,
             MultiParamTypeClasses,
             FunctionalDependencies,
             UndecidableInstances,
             ScopedTypeVariables,
             TypeFamilies,
             InstanceSigs,
             AllowAmbiguousTypes,
             TypeApplications,
             PatternSynonyms,
             PartialTypeSignatures
#-}

module Data.HList where

import Data.Kind
import Data.Proxy
import Data.Label
import Data.Type.Bool
import Data.Type.Equality

-- |Heterogeneous lists are implemented as a GADT
data HList (l :: [Type]) :: Type  where
  HNil :: HList '[]
  HCons :: x -> HList xs -> HList (x ': xs)

hHead :: HList (t ': _) -> t
hHead (HCons v _) = v


-- | HMember is a test membership function.
--Since we are in Haskell the value level function computes with the evidence 
class HMember (t :: Type) (l :: [Type]) where
  type HMemberRes t l :: Bool
  hMember :: Label t -> HList l -> Proxy (HMemberRes t l)

instance HMember t '[] where
  type HMemberRes t '[] = 'False
  hMember _ _ = Proxy

instance HMember t (t' ': ts) where
  type HMemberRes t (t' ': ts) = t == t' || HMemberRes t ts
  hMember _ _ = Proxy

-- | HMember' is a test membership function.
-- But looking up in a list of Labels
class HMember' (t :: k) (l :: [k]) where
  type HMemberRes' t l :: Bool
  hMember' :: f t -> LList l -> Proxy (HMemberRes' t l)

instance HMember' t '[] where
  type HMemberRes' t '[] = 'False
  hMember' _ _ = Proxy

instance HMember' t (t' ': ts) where
  type HMemberRes' t (t' ': ts) = t == t' || HMemberRes' t ts
  hMember' _ _ = Proxy


-- | No other functionality is needed for AAG

infixr 2 .:
(.:) = HCons
ε = HNil
hn = HNil

-- | a polykinded heteogeneous list of labels
data LList (l :: [k]) :: Type where
  LNil :: LList '[]
  LCons :: Label h -> LList l -> LList (h ': l)

infixr 2 .:.
(.:.) = LCons
lL = LNil

lHead :: LList (t ': ts) -> Label t
lHead _ = Label

class LListFrom (l :: [k]) where
  lListFrom :: Proxy l -> LList l

instance LListFrom ('[] :: [k]) where
  lListFrom (Proxy :: Proxy '[])= LNil

instance LListFrom ts => LListFrom (t ': ts) where
  lListFrom (Proxy :: Proxy (t ': ts))
    = LCons Label $ lListFrom Proxy

type family Snoc (l :: [k]) (v :: k) where
  Snoc '[]       v  = '[v]
  Snoc (x ': xs) v  = x ': Snoc xs v