type-combinators 0.1.0.1 → 0.1.2.0
raw patch · 14 files changed
+664/−129 lines, 14 filesdep +containersdep +mtldep +template-haskell
Dependencies added: containers, mtl, template-haskell, transformers
Files
- src/Data/Type/Combinator.hs +61/−0
- src/Data/Type/Conjunction.hs +1/−1
- src/Data/Type/Index.hs +0/−2
- src/Data/Type/Index/Quote.hs +48/−0
- src/Data/Type/Nat/Quote.hs +89/−0
- src/Data/Type/Product.hs +51/−11
- src/Data/Type/Product/Dual.hs +184/−0
- src/Data/Type/Quantifier.hs +8/−4
- src/Data/Type/Sum.hs +7/−38
- src/Data/Type/Sum/Dual.hs +125/−0
- src/Type/Class/Witness.hs +5/−0
- src/Type/Family/Pair.hs +0/−58
- src/Type/Family/Tuple.hs +70/−0
- type-combinators.cabal +15/−15
src/Data/Type/Combinator.hs view
@@ -34,6 +34,7 @@ import Type.Class.HFunctor import Type.Class.Known import Type.Class.Witness+import Type.Family.Tuple import Control.Applicative @@ -293,6 +294,66 @@ flipped :: (f a b -> g c d) -> Flip f b a -> Flip g d c flipped f = Flip . f . getFlip++-- }}}++-- Cur {{{++newtype Cur (p :: (k,l) -> *) :: k -> l -> * where+ Cur :: { getCur :: p (a#b) } -> Cur p a b++instance Known p (a#b) => Known (Cur p a) b where+ type KnownC (Cur p a) b = Known p (a#b)+ known = Cur known++instance Witness q r (p (a#b)) => Witness q r (Cur p a b) where+ type WitnessC q r (Cur p a b) = Witness q r (p (a#b))+ r \\ Cur p = r \\ p++-- }}}++-- Uncur {{{++data Uncur (p :: k -> l -> *) :: (k,l) -> * where+ Uncur :: { getUncur :: p a b } -> Uncur p (a#b)++instance (Known (p a) b,q ~ (a#b)) => Known (Uncur p) q where+ type KnownC (Uncur p) q = Known (p (Fst q)) (Snd q)+ known = Uncur known++instance (Witness r s (p a b),q ~ (a#b)) => Witness r s (Uncur p q) where+ type WitnessC r s (Uncur p q) = Witness r s (p (Fst q) (Snd q))+ r \\ Uncur p = r \\ p++-- }}}++-- Cur {{{++newtype Cur3 (p :: (k,l,m) -> *) :: k -> l -> m -> * where+ Cur3 :: { getCur3 :: p '(a,b,c) } -> Cur3 p a b c++instance Known p '(a,b,c) => Known (Cur3 p a b) c where+ type KnownC (Cur3 p a b) c = Known p '(a,b,c)+ known = Cur3 known++instance Witness q r (p '(a,b,c)) => Witness q r (Cur3 p a b c) where+ type WitnessC q r (Cur3 p a b c) = Witness q r (p '(a,b,c))+ r \\ Cur3 p = r \\ p++-- }}}++-- Uncur3 {{{++data Uncur3 (p :: k -> l -> m -> *) :: (k,l,m) -> * where+ Uncur3 :: { getUncur3 :: p a b c } -> Uncur3 p '(a,b,c)++instance (Known (p a b) c,q ~ '(a,b,c)) => Known (Uncur3 p) q where+ type KnownC (Uncur3 p) q = Known (p (Fst3 q) (Snd3 q)) (Thd3 q)+ known = Uncur3 known++instance (Witness r s (p a b c),q ~ '(a,b,c)) => Witness r s (Uncur3 p q) where+ type WitnessC r s (Uncur3 p q) = Witness r s (p (Fst3 q) (Snd3 q) (Thd3 q))+ r \\ Uncur3 p = r \\ p -- }}}
src/Data/Type/Conjunction.hs view
@@ -35,7 +35,7 @@ import Type.Class.HFunctor import Type.Class.Known import Type.Class.Witness-import Type.Family.Pair+import Type.Family.Tuple -- (:&:) {{{
src/Data/Type/Index.hs view
@@ -33,8 +33,6 @@ import Type.Family.List import Type.Family.Nat --- | 'IZ' indexes the head of the list,--- and 'IS' indexes into the tail of the list. data Index :: [k] -> k -> * where IZ :: Index (a :< as) a IS :: !(Index as a) -> Index (b :< as) a
+ src/Data/Type/Index/Quote.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE LambdaCase #-}+-----------------------------------------------------------------------------+-- |+-- Module : Data.Type.Index.Quote+-- Copyright : Copyright (C) 2015 Kyle Carter+-- License : BSD3+--+-- Maintainer : Kyle Carter <kylcarte@indiana.edu>+-- Stability : experimental+-- Portability : RankNTypes+--+-- A 'QuasiQuoter' for the 'Index' type.+--+-----------------------------------------------------------------------------++module Data.Type.Index.Quote where++import Data.Type.Index+import Language.Haskell.TH+import Language.Haskell.TH.Lib+import Language.Haskell.TH.Quote+import Text.Read (readMaybe)+import Control.Monad++ix :: QuasiQuoter+ix = QuasiQuoter+ { quoteExp = parseIxExp+ , quotePat = error "ix: quotePat not defined"+ , quoteType = error "ix: quoteType not defined"+ , quoteDec = error "ix: quoteDec not defined"+ }++parseIxExp :: String -> Q Exp+parseIxExp s = maybe (fail $ "ix: couldn't parse Int: " ++ show s)+ (notNeg >=> go)+ $ readMaybe s+ where+ notNeg :: Int -> Q Int+ notNeg n+ | n < 0 = fail $ "ix: negative index: " ++ show n+ | True = return n+ go :: Int -> Q Exp+ go = \case+ 0 -> [| IZ |]+ n -> [| IS $(go $ n-1) |]+
+ src/Data/Type/Nat/Quote.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+-----------------------------------------------------------------------------+-- |+-- Module : Data.Type.Index.Quote+-- Copyright : Copyright (C) 2015 Kyle Carter+-- License : BSD3+--+-- Maintainer : Kyle Carter <kylcarte@indiana.edu>+-- Stability : experimental+-- Portability : RankNTypes+--+-- A 'QuasiQuoter' for the 'N' kind and the 'Nat' type.+--+-----------------------------------------------------------------------------++module Data.Type.Nat.Quote where++import Data.Type.Nat+import Type.Family.Nat+import Language.Haskell.TH+import Language.Haskell.TH.Quote+import Control.Monad+import Text.Read (readMaybe)++n :: QuasiQuoter+n = QuasiQuoter+ { quoteExp = parseNatExp+ , quotePat = parseNatPat+ , quoteType = parseNatType+ , quoteDec = error "n: quoteDec not defined"+ }++parseNatExp :: String -> Q Exp+parseNatExp s = maybe (fail $ "n: couldn't parse Int: " ++ show s)+ (notNeg >=> go)+ $ readMaybe s+ where+ notNeg :: Int -> Q Int+ notNeg n+ | n < 0 = fail $ "n: negative: " ++ show n+ | True = return n+ go :: Int -> Q Exp+ go = \case+ 0 -> [| Z_ |]+ n -> [| S_ $(go $ n-1) |]++parseNatPat :: String -> Q Pat+parseNatPat s = maybe (fail $ "n: couldn't parse Int: " ++ show s)+ (notNeg >=> go)+ $ readMaybe s+ where+ notNeg :: Int -> Q Int+ notNeg n+ | n < 0 = fail $ "n: negative: " ++ show n+ | True = return n+ go :: Int -> Q Pat+ go = \case+ 0 -> [p| Z_ |]+ n -> [p| S_ $(go $ n-1) |]++parseNatType :: String -> Q Type+parseNatType s = maybe (fail $ "n: couldn't parse Int: " ++ show s)+ (notNeg >=> go)+ $ readMaybe s+ where+ notNeg :: Int -> Q Int+ notNeg n+ | n < 0 = fail $ "n: negative: " ++ show n+ | True = return n+ go :: Int -> Q Type+ go = \case+ 0 -> [t| Z |]+ n -> [t| S $(go $ n-1) |]+
src/Data/Type/Product.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE StandaloneDeriving #-}@@ -37,7 +38,7 @@ module Data.Type.Product where -import Data.Type.Combinator ((:.:)(..),IT(..))+import Data.Type.Combinator ((:.:)(..),IT(..),I(..)) import Data.Type.Index import Data.Type.Length import Type.Class.HFunctor@@ -46,49 +47,88 @@ import Type.Family.Constraint import Type.Family.List +import Control.Arrow ((&&&))+ data Prod (f :: k -> *) :: [k] -> * where Ø :: Prod f Ø (:<) :: !(f a) -> !(Prod f as) -> Prod f (a :< as) infixr 5 :< +-- | Construct a two element Prod.+-- Since the precedence of (:>) is higher than (:<),+-- we can conveniently write lists like:+--+-- >>> a :< b :> c+--+-- Which is identical to:+--+-- >>> a :< b :< c :< Ø+-- pattern (:>) :: (f :: k -> *) (a :: k) -> f (b :: k) -> Prod f '[a,b] pattern a :> b = a :< b :< Ø infix 6 :> +-- | Build a singleton Prod. only :: f a -> Prod f '[a] only = (:< Ø) -head' :: Prod f (a :< as) -> f a-head' (a :< _) = a--tail' :: Prod f (a :< as) -> Prod f as-tail' (_ :< as) = as-+-- | snoc function. insert an element at the end of the list. (>:) :: Prod f as -> f a -> Prod f (as >: a) (>:) = \case Ø -> only b :< as -> (b :<) . (as >:) infixl 6 >: -reverse' :: Prod f as -> Prod f (Reverse as)-reverse' = \case- Ø -> Ø- a :< as -> reverse' as >: a+head' :: Prod f (a :< as) -> f a+head' (a :< _) = a +tail' :: Prod f (a :< as) -> Prod f as+tail' (_ :< as) = as++-- | Get all but the last element of a non-empty Prod. init' :: Prod f (a :< as) -> Prod f (Init' a as) init' (a :< as) = case as of Ø -> Ø (:<){} -> a :< init' as +-- | Get the last element of a non-empty Prod. last' :: Prod f (a :< as) -> f (Last' a as) last' (a :< as) = case as of Ø -> a (:<){} -> last' as +reverse' :: Prod f as -> Prod f (Reverse as)+reverse' = \case+ Ø -> Ø+ a :< as -> reverse' as >: a+ append' :: Prod f as -> Prod f bs -> Prod f (as ++ bs) append' = \case Ø -> id a :< as -> (a :<) . append' as++-- Tuple {{{++-- | A Prod of simple Haskell types.+type Tuple = Prod I++-- | Singleton Tuple.+only_ :: a -> Tuple '[a]+only_ = only . I++-- | Cons onto a Tuple.+pattern (::<) :: a -> Tuple as -> Tuple (a :< as)+pattern a ::< as = I a :< as+infixr 5 ::<++-- | Snoc onto a Tuple.+(>::) :: Tuple as -> a -> Tuple (as >: a)+(>::) = \case+ Ø -> only_+ b :< as -> (b :<) . (as >::)+infixl 6 >::++-- }}} onHead' :: (f a -> f b) -> Prod f (a :< as) -> Prod f (b :< as) onHead' f (a :< as) = f a :< as
+ src/Data/Type/Product/Dual.hs view
@@ -0,0 +1,184 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+-----------------------------------------------------------------------------+-- |+-- Module : Data.Type.Product.Dual+-- Copyright : Copyright (C) 2015 Kyle Carter+-- License : BSD3+--+-- Maintainer : Kyle Carter <kylcarte@indiana.edu>+-- Stability : experimental+-- Portability : RankNTypes+--+-- Type combinators for type-level lists,+-- where we have many functors with a single index.+--+-----------------------------------------------------------------------------++module Data.Type.Product.Dual where++import Data.Type.Combinator ((:.:)(..),IT(..),I(..))+import Data.Type.Index+import Data.Type.Length+import Type.Class.HFunctor+import Type.Class.Known+import Type.Class.Witness+import Type.Family.Constraint+import Type.Family.List++import Control.Arrow ((&&&))+import Data.Monoid ((<>))++data FProd (fs :: [k -> *]) :: k -> * where+ ØF :: FProd Ø a+ (:<<) :: !(f a) -> !(FProd fs a) -> FProd (f :< fs) a+infixr 5 :<<++-- | Construct a two element FProd.+-- Since the precedence of (:>>) is higher than (:<<),+-- we can conveniently write lists like:+--+-- >>> a :<< b :>> c+--+-- Which is identical to:+--+-- >>> a :<< b :<< c :<< Ø+--+pattern (:>>) :: (f :: k -> *) (a :: k) -> (g :: k -> *) a -> FProd '[f,g] a+pattern a :>> b = a :<< b :<< ØF+infix 6 :>>++-- | Build a singleton FProd.+onlyF :: f a -> FProd '[f] a+onlyF = (:<< ØF)++-- | snoc function. insert an element at the end of the FProd.+(>>:) :: FProd fs a -> f a -> FProd (fs >: f) a+(>>:) = \case+ ØF -> onlyF+ b :<< as -> (b :<<) . (as >>:)+infixl 6 >>:++headF :: FProd (f :< fs) a -> f a+headF (a :<< _) = a++tailF :: FProd (f :< fs) a -> FProd fs a+tailF (_ :<< as) = as++-- | Get all but the last element of a non-empty FProd.+initF :: FProd (f :< fs) a -> FProd (Init' f fs) a+initF (a :<< as) = case as of+ ØF -> ØF+ (:<<){} -> a :<< initF as++-- | Get the last element of a non-empty FProd.+lastF :: FProd (f :< fs) a -> Last' f fs a+lastF (a :<< as) = case as of+ ØF -> a+ (:<<){} -> lastF as++-- | Reverse the elements of an FProd.+reverseF :: FProd fs a -> FProd (Reverse fs) a+reverseF = \case+ ØF -> ØF+ a :<< as -> reverseF as >>: a++-- | Append two FProds.+appendF :: FProd fs a -> FProd gs a -> FProd (fs ++ gs) a+appendF = \case+ ØF -> id+ a :<< as -> (a :<<) . appendF as++-- | Map over the head of a non-empty FProd.+onHeadF :: (f a -> g a) -> FProd (f :< fs) a -> FProd (g :< fs) a+onHeadF f (a :<< as) = f a :<< as++-- | Map over the tail of a non-empty FProd.+onTailF :: (FProd fs a -> FProd gs a) -> FProd (f :< fs) a -> FProd (f :< gs) a+onTailF f (a :<< as) = a :<< f as++uncurryF :: (f a -> FProd fs a -> r) -> FProd (f :< fs) a -> r+uncurryF f (a :<< as) = f a as++curryF :: (l ~ (f :< fs)) => (FProd l a -> r) -> f a -> FProd fs a -> r+curryF f a as = f $ a :<< as++indexF :: Index fs f -> FProd fs a -> f a+indexF = \case+ IZ -> headF+ IS x -> indexF x . tailF++-- | If all @f@ in @fs@ are @Functor@s, then @FProd fs@ is a @Functor@.+instance ListC (Functor <$> fs) => Functor (FProd fs) where+ fmap f = \case+ ØF -> ØF+ a :<< as -> fmap f a :<< fmap f as++-- | If all @f@ in @fs@ are @Foldable@s, then @FProd fs@ is a @Foldable@.+instance ListC (Foldable <$> fs) => Foldable (FProd fs) where+ foldMap f = \case+ ØF -> mempty+ a :<< as -> foldMap f a <> foldMap f as++-- | If all @f@ in @fs@ are @Traversable@s, then @FProd fs@ is a @Traversable@.+instance+ ( ListC (Functor <$> fs)+ , ListC (Foldable <$> fs)+ , ListC (Traversable <$> fs)+ ) => Traversable (FProd fs) where+ traverse f = \case+ ØF -> pure ØF+ a :<< as -> (:<<) <$> traverse f a <*> traverse f as++-- | Map over all elements of an FProd with access to the element's index.+imapF :: (forall f. Index fs f -> f a -> f b)+ -> FProd fs a -> FProd fs b+imapF f = \case+ ØF -> ØF+ a :<< as -> f IZ a :<< imapF (f . IS) as++-- | Fold over all elements of an FProd with access to the element's index.+ifoldMapF :: Monoid m+ => (forall f. Index fs f -> f a -> m)+ -> FProd fs a -> m+ifoldMapF f = \case+ ØF -> mempty+ a :<< as -> f IZ a <> ifoldMapF (f . IS) as++-- | Traverse over all elements of an FProd with access to the element's index.+itraverseF :: Applicative g+ => (forall f. Index fs f -> f a -> g (f b))+ -> FProd fs a -> g (FProd fs b)+itraverseF f = \case+ ØF -> pure ØF+ a :<< as -> (:<<) <$> f IZ a <*> itraverseF (f . IS) as++instance Known (FProd Ø) a where+ known = ØF++instance (Known f a, Known (FProd fs) a) => Known (FProd (f :< fs)) a where+ type KnownC (FProd (f :< fs)) a = (Known f a, Known (FProd fs) a)+ known = known :<< known++-- | An empty FProd is a no-op Witness.+instance Witness ØC ØC (FProd Ø a) where+ r \\ _ = r++-- | A non-empty FProd is a Witness if both its head and tail are Witnesses.+instance (Witness p q (f a), Witness s t (FProd fs a)) => Witness (p,s) (q,t) (FProd (f :< fs) a) where+ type WitnessC (p,s) (q,t) (FProd (f :< fs) a) = (Witness p q (f a), Witness s t (FProd fs a))+ r \\ (a :<< as) = r \\ a \\ as+
src/Data/Type/Quantifier.hs view
@@ -40,14 +40,18 @@ -- | An eliminator for a 'Some' type. ----- NB: the result type of the eliminating function may--- not refer to the universally quantified type index @a@.+-- Consider this function akin to a Monadic bind, except+-- instead of binding into a Monad with a sequent function,+-- we're binding into the existential quantification with+-- a universal eliminator function. ----- This function deserves more documentation. It is a powerful--- basis for working with correct-by-construction data. -- It serves as an explicit delimiter in a program of where -- the type index may be used and depended on, and where it may -- not.+--+-- NB: the result type of the eliminating function may+-- not refer to the universally quantified type index @a@.+-- some :: Some f -> (forall a. f a -> r) -> r some (Some a) f = f a
src/Data/Type/Sum.hs view
@@ -22,10 +22,9 @@ -- Stability : experimental -- Portability : RankNTypes ----- 'Sum' and 'SumF' are type combinators for representing disjoint sums of--- indices @(as :: [k])@ of a single functor @(f :: k -> *), or of--- many functors @(fs :: [k -> *])@ at a single index @(a :: k)@,--- respectively.+-- 'Sum' is a type combinators for representing disjoint sums of+-- indices @(as :: [k])@ of a single functor @(f :: k -> *).+-- Contrast to the many-functors-one-index 'FSum' -- ----------------------------------------------------------------------------- @@ -43,6 +42,10 @@ InL :: !(f a) -> Sum f (a :< as) InR :: !(Sum f as) -> Sum f (a :< as) +-- | There are no possible values of the type @Sum f Ø@.+nilSum :: Sum f Ø -> Void+nilSum = impossible+ decomp :: Sum f (a :< as) -> Either (f a) (Sum f as) decomp = \case InL a -> Left a@@ -113,38 +116,4 @@ InR s -> r \\ s -- }}}--data SumF :: [k -> *] -> k -> * where- InLF :: !(f a) -> SumF (f :< fs) a- InRF :: !(SumF fs a) -> SumF (f :< fs) a--instance ListC (Functor <$> fs) => Functor (SumF fs) where- fmap f = \case- InLF a -> InLF $ f <$> a- InRF s -> InRF $ f <$> s--decompF :: SumF (f :< fs) a -> Either (f a) (SumF fs a)-decompF = \case- InLF a -> Left a- InRF s -> Right s--injF :: (f ∈ fs) => f a -> SumF fs a-injF = injectSumF elemIndex--prjF :: (f ∈ fs) => SumF fs a -> Maybe (f a)-prjF = indexF elemIndex--injectSumF :: Index fs f -> f a -> SumF fs a-injectSumF = \case- IZ -> InLF- IS x -> InRF . injectSumF x--indexF :: Index fs f -> SumF fs a -> Maybe (f a)-indexF = \case- IZ -> \case- InLF a -> Just a- _ -> Nothing- IS x -> \case- InRF s -> indexF x s- _ -> Nothing
+ src/Data/Type/Sum/Dual.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+-----------------------------------------------------------------------------+-- |+-- Module : Data.Type.Sum.Dual+-- Copyright : Copyright (C) 2015 Kyle Carter+-- License : BSD3+--+-- Maintainer : Kyle Carter <kylcarte@indiana.edu>+-- Stability : experimental+-- Portability : RankNTypes+--+-- 'FSum' is a type combinators for representing disjoint sums of+-- many functors @(fs :: [k -> *])@ at a single index @(a :: k)@.+-- As opposed to one-functor-many-indices 'Sum'.+--+-----------------------------------------------------------------------------++module Data.Type.Sum.Dual where++import Data.Type.Index++import Type.Class.HFunctor+import Type.Class.Witness++import Type.Family.Constraint+import Type.Family.List++data FSum :: [k -> *] -> k -> * where+ FInL :: !(f a) -> FSum (f :< fs) a+ FInR :: !(FSum fs a) -> FSum (f :< fs) a++-- | There are no possible values of the type @FSum Ø a@.+nilSumF :: FSum Ø a -> Void+nilSumF = impossible++-- | Decompose a non-empty FSum into either its head or its tail.+decompF :: FSum (f :< fs) a -> Either (f a) (FSum fs a)+decompF = \case+ FInL a -> Left a+ FInR s -> Right s++-- | Inject an element into an FSum.+injF :: (f ∈ fs) => f a -> FSum fs a+injF = injectFSum elemIndex++-- | Project an implicit index out of an FSum.+prjF :: (f ∈ fs) => FSum fs a -> Maybe (f a)+prjF = indexF elemIndex++-- | Inject an element into an FSum with an explicitly+-- specified Index.+injectFSum :: Index fs f -> f a -> FSum fs a+injectFSum = \case+ IZ -> FInL+ IS x -> FInR . injectFSum x++-- | Project an explicit index out of an FSum.+indexF :: Index fs f -> FSum fs a -> Maybe (f a)+indexF = \case+ IZ -> \case+ FInL a -> Just a+ _ -> Nothing+ IS x -> \case+ FInR s -> indexF x s+ _ -> Nothing++instance ListC (Functor <$> fs) => Functor (FSum fs) where+ fmap f = \case+ FInL a -> FInL $ f <$> a+ FInR s -> FInR $ f <$> s++instance ListC (Foldable <$> fs) => Foldable (FSum fs) where+ foldMap f = \case+ FInL a -> foldMap f a+ FInR s -> foldMap f s++instance+ ( ListC (Functor <$> fs)+ , ListC (Foldable <$> fs)+ , ListC (Traversable <$> fs)+ ) => Traversable (FSum fs) where+ traverse f = \case+ FInL a -> FInL <$> traverse f a+ FInR s -> FInR <$> traverse f s++-- | Map over the single element in an FSum+-- with a function that can handle any possible+-- element, along with the element's index.+imapF :: (forall f. Index fs f -> f a -> f b)+ -> FSum fs a -> FSum fs b+imapF f = \case+ FInL a -> FInL $ f IZ a+ FInR s -> FInR $ imapF (f . IS) s++-- | Fun fact: Since there is exactly one element in+-- an FSum, we don't need the @Monoid@ instance!+ifoldMapF :: (forall f. Index fs f -> f a -> m)+ -> FSum fs a -> m+ifoldMapF f = \case+ FInL a -> f IZ a+ FInR s -> ifoldMapF (f . IS) s++-- | Another fun fact: Since there is exactly one element in+-- an FSum, we require only a @Functor@ instance on @g@, rather+-- than @Applicative@.+itraverseF :: Functor g+ => (forall f. Index fs f -> f a -> g (f b))+ -> FSum fs a -> g (FSum fs b)+itraverseF f = \case+ FInL a -> FInL <$> f IZ a+ FInR s -> FInR <$> itraverseF (f . IS) s+
src/Type/Class/Witness.hs view
@@ -77,6 +77,9 @@ id = Sub Wit Sub bc . Sub ab = Sub $ bc \\ ab +type (:-:) = Bij (:-)+infixr 4 :-:+ -- | A general eliminator for entailment. -- -- Given a term of type @t@ with an instance @Witness p q t@@@ -159,6 +162,7 @@ id = Bij id id g . f = Bij (fwd g . fwd f) (bwd f . bwd g) +{- class Category c => Monoidal (c :: k -> k -> *) where type Tensor c :: k -> k -> k type Unit c :: k@@ -193,6 +197,7 @@ (***) :: Monoidal p => Bij p a b -> Bij p c d -> Bij p (Tensor p a c) (Tensor p b d) f *** g = (fwd f .*. fwd g) <-> (bwd f .*. bwd g) infixr 3 ***+-} type (<->) = Bij (->) infixr 5 <->
− src/Type/Family/Pair.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE GADTs #-}--------------------------------------------------------------------------------- |--- Module : Type.Family.Pair--- Copyright : Copyright (C) 2015 Kyle Carter--- License : BSD3------ Maintainer : Kyle Carter <kylcarte@indiana.edu>--- Stability : experimental--- Portability : RankNTypes------ Type-level pairs, along with some convenient aliases and type families--- over them.-----------------------------------------------------------------------------------module Type.Family.Pair where--import Type.Family.Monoid--type (#) = '(,)-infixr 6 #--type family Fst (p :: (k,l)) :: k where- Fst '(a,b) = a--type family Snd (p :: (k,l)) :: l where- Snd '(a,b) = b--type family (f :: k -> l) <$> (a :: (m,k)) :: (m,l) where- f <$> (a#b) = a # f b-infixr 4 <$>--type family (f :: (m,k -> l)) <&> (a :: k) :: (m,l) where- (r#f) <&> a = r # f a-infixr 4 <&>--type family (f :: (m,k -> l)) <*> (a :: (m,k)) :: (m,l) where- (r#f) <*> (s#a) = (r <> s) # f a-infixr 4 <*>---- | A type-level pair is a Monoid over its pairwise components.-type instance Mempty = Mempty # Mempty-type instance (r#a) <> (s#b) = (r <> s) # (a <> b)-
+ src/Type/Family/Tuple.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+-----------------------------------------------------------------------------+-- |+-- Module : Type.Family.Tuple+-- Copyright : Copyright (C) 2015 Kyle Carter+-- License : BSD3+--+-- Maintainer : Kyle Carter <kylcarte@indiana.edu>+-- Stability : experimental+-- Portability : RankNTypes+--+-- Type-level pairs and triples, along with some convenient aliases and type families+-- over them.+--+-----------------------------------------------------------------------------++module Type.Family.Tuple where++import Type.Family.Monoid++type (#) = '(,)+infixr 6 #++type family Fst (p :: (k,l)) :: k where+ Fst '(a,b) = a++type family Snd (p :: (k,l)) :: l where+ Snd '(a,b) = b++type family (f :: k -> l) <$> (a :: (m,k)) :: (m,l) where+ f <$> (a#b) = a # f b+infixr 4 <$>++type family (f :: (m,k -> l)) <&> (a :: k) :: (m,l) where+ (r#f) <&> a = r # f a+infixr 4 <&>++type family (f :: (m,k -> l)) <*> (a :: (m,k)) :: (m,l) where+ (r#f) <*> (s#a) = (r <> s) # f a+infixr 4 <*>++-- | A type-level pair is a Monoid over its pairwise components.+type instance Mempty = Mempty # Mempty+type instance (r#a) <> (s#b) = (r <> s) # (a <> b)++type family Fst3 (p :: (k,l,m)) :: k where+ Fst3 '(a,b,c) = a++type family Snd3 (p :: (k,l,m)) :: l where+ Snd3 '(a,b,c) = b++type family Thd3 (p :: (k,l,m)) :: m where+ Thd3 '(a,b,c) = c++type instance Mempty = '(Mempty,Mempty,Mempty)+type instance '(a,b,c) <> '(d,e,f) = '(a<>d,b<>e,c<>f)+
type-combinators.cabal view
@@ -1,24 +1,16 @@ name: type-combinators+version: 0.1.2.0 category: Data-synopsis: A collection of data types for type-level programming.-description: I put this library together first and foremost so that- I wouldn't need to constantly rewrite the same code- that uses these types, but also because I noticed a- growing trend of writing and rewriting bits and pieces- of code for these types all over the Haskell community.- Hopefully, this helps! Contributions, criticisms, and- thoughts are very welcome. -kylcarte-homepage: http://github.com/kylcarte/type-combinators-bug-reports: http://github.com/type-combinators/issues-version: 0.1.0.1+synopsis: A collection of data types for type-level programming cabal-version: >=1.10 build-type: Simple license: BSD3 license-file: LICENSE maintainer: kylcarte@gmail.com author: Kyle Carter+homepage: https://github.com/kylcarte/type-combinators -source-repository head+Source-Repository head type: git location: git://github.com/kylcarte/type-combinators.git @@ -29,12 +21,16 @@ Data.Type.Disjunction Data.Type.Fin Data.Type.Index+ Data.Type.Index.Quote Data.Type.Length Data.Type.Nat+ Data.Type.Nat.Quote Data.Type.Option Data.Type.Product- Data.Type.Quantifier+ Data.Type.Product.Dual Data.Type.Sum+ Data.Type.Sum.Dual+ Data.Type.Quantifier Data.Type.Vector Type.Class.HFunctor Type.Class.Known@@ -44,9 +40,13 @@ Type.Family.Maybe Type.Family.Monoid Type.Family.Nat- Type.Family.Pair+ Type.Family.Tuple build-depends:- base >=4.8 && <4.9+ base >=4.8 && <4.9,+ containers,+ template-haskell,+ transformers,+ mtl default-language: Haskell2010 hs-source-dirs: src