{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE GADTs #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Type.Subset -- Copyright : Copyright (C) 2015 Kyle Carter -- License : BSD3 -- -- Maintainer : Kyle Carter -- Stability : experimental -- Portability : RankNTypes -- -- A @singleton@-esque type for representing subsets of a type level list. -- ----------------------------------------------------------------------------- module Data.Type.Subset ( module Data.Type.Subset , module Exports ) where -- import Data.Type.Quantifier import Type.Class.Higher import Type.Class.Known import Type.Class.Witness import Type.Family.List import Data.Type.Index import Data.Type.Length import Data.Type.Product as Exports (Prod(..)) import Data.Type.Product (index) import Data.Type.Sum (Sum(..),prj) import Control.Applicative ((<|>)) type Subset as = Prod (Index as) subNil :: Subset Ø as -> (as :~: Ø) subNil = \case Ø -> Refl x :< _ -> ixNil x type as ⊆ bs = Every (Elem bs) as infix 4 ⊆ subRefl :: Known Length as => Subset as as subRefl = go known where go :: Length xs -> Subset xs xs go = \case LZ -> Ø LS l -> IZ :< map1 IS (go l) subTrans :: Subset as bs -> Subset bs cs -> Subset as cs subTrans s = map1 $ subIx s subProd :: Subset as bs -> Prod f as -> Prod f bs subProd = \case Ø -> pure Ø x :< s -> (:<) <$> index x <*> subProd s subSum :: Subset as bs -> Sum f as -> Maybe (Sum f bs) subSum = \case Ø -> pure Nothing x :< s -> \t -> (InL <$> (prj t \\ x)) <|> (InR <$> subSum s t) subIx :: Subset as bs -> Index bs x -> Index as x subIx = \case Ø -> ixNil x :< s -> \case IZ -> x IS y -> subIx s y subExt :: Known Length as => (forall x. Index as x -> Index bs x) -> Subset bs as subExt f = subExtBy f known subExtBy :: (forall x. Index as x -> Index bs x) -> Length as -> Subset bs as subExtBy f = \case LZ -> Ø LS l -> f IZ :< subExtBy (f . IS) l