tuple-sop 0.3.0.0 → 0.3.1.0
raw patch · 3 files changed
+185/−1 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Tuple.Ops: appF :: AppF f s t => f -> s -> t
+ Data.Tuple.Ops: foldlT :: FoldLeft f s t => f -> t -> s -> t
+ Data.Tuple.Ops: foldrT :: FoldRight f s t => f -> t -> s -> t
+ Data.Tuple.Ops: ins :: Insert a s t => a -> s -> t
+ Data.Tuple.Ops: ins1 :: InsertN a s 0 t => a -> s -> t
+ Data.Tuple.Ops: ins10 :: InsertN a s 9 t => a -> s -> t
+ Data.Tuple.Ops: ins2 :: InsertN a s 1 t => a -> s -> t
+ Data.Tuple.Ops: ins3 :: InsertN a s 2 t => a -> s -> t
+ Data.Tuple.Ops: ins4 :: InsertN a s 3 t => a -> s -> t
+ Data.Tuple.Ops: ins5 :: InsertN a s 4 t => a -> s -> t
+ Data.Tuple.Ops: ins6 :: InsertN a s 5 t => a -> s -> t
+ Data.Tuple.Ops: ins7 :: InsertN a s 6 t => a -> s -> t
+ Data.Tuple.Ops: ins8 :: InsertN a s 7 t => a -> s -> t
+ Data.Tuple.Ops: ins9 :: InsertN a s 8 t => a -> s -> t
+ Data.Tuple.Ops: insN :: InsertN a s n t => a -> s -> Proxy n -> t
+ Data.Tuple.Ops: instance (Data.Tuple.Ops.GenericNP s rep_s, Data.Tuple.Ops.GAppF f rep_s t) => Data.Tuple.Ops.AppF f s t
+ Data.Tuple.Ops: instance (Data.Tuple.Ops.GenericNP s rep_s, Data.Tuple.Ops.GFoldLeft f rep_s t) => Data.Tuple.Ops.FoldLeft f s t
+ Data.Tuple.Ops: instance (Data.Tuple.Ops.GenericNP s rep_s, Data.Tuple.Ops.GFoldRight f rep_s t) => Data.Tuple.Ops.FoldRight f s t
+ Data.Tuple.Ops: instance (Data.Tuple.Ops.GenericNP s rep_s, Data.Tuple.Ops.GenericNP t rep_t, Data.Tuple.Ops.GInsert (Data.Tuple.Ops.InsLoc a rep_s rep_t) a rep_s rep_t) => Data.Tuple.Ops.Insert a s t
+ Data.Tuple.Ops: instance (Data.Tuple.Ops.GenericNP s rep_s, Data.Tuple.Ops.GenericNP t rep_t, Data.Tuple.Ops.GInsertN a rep_s (Data.Tuple.Ops.Lit n) rep_t) => Data.Tuple.Ops.InsertN a s n t
+ Data.Tuple.Ops: instance (a ~ a', Data.Tuple.Ops.GAppF b (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) c) => Data.Tuple.Ops.GAppF (a -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (a' : xs)) c
+ Data.Tuple.Ops: instance (a ~ a', Data.Tuple.Ops.GFoldLeft (b -> a -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) b) => Data.Tuple.Ops.GFoldLeft (b -> a -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (a' : xs)) b
+ Data.Tuple.Ops: instance (a ~ a', b ~ b', Data.Tuple.Ops.GFoldRight (a -> b' -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) b) => Data.Tuple.Ops.GFoldRight (a -> b' -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (a' : xs)) b
+ Data.Tuple.Ops: instance (b ~ c, Data.Tuple.Ops.GInsert n a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs')) => Data.Tuple.Ops.GInsert ('Data.Tuple.Ops.S' n) a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (b : xs)) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (c : xs'))
+ Data.Tuple.Ops: instance Data.Tuple.Ops.GFoldLeft (b -> a -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I '[]) b
+ Data.Tuple.Ops: instance Data.Tuple.Ops.GFoldRight (a -> b -> b) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I '[]) b
+ Data.Tuple.Ops: instance Data.Tuple.Ops.GInsert 'Data.Tuple.Ops.Z' a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (a : xs))
+ Data.Tuple.Ops: instance Data.Tuple.Ops.GInsertN a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) 'Data.Tuple.Ops.Z' (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (a : xs))
+ Data.Tuple.Ops: instance Data.Tuple.Ops.GInsertN a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs) n (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I xs') => Data.Tuple.Ops.GInsertN a (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (b : xs)) ('Data.Tuple.Ops.S' n) (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I (b : xs'))
+ Data.Tuple.Ops: instance b ~ b' => Data.Tuple.Ops.GAppF b (Generics.SOP.NP.NP Generics.SOP.BasicFunctors.I '[]) b'
Files
- ChangeLog.md +4/−0
- src/Data/Tuple/Ops.hs +180/−0
- tuple-sop.cabal +1/−1
ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for tuple-sop +## 0.3.1.0 -- 2018-06-24++* Added insertion, folding and application functions.+ ## 0.3.0.0 -- 2018-05-08 * Improved type inference. One minor breaking change in the use of mapT on polymorphic n-ary tuples.
src/Data/Tuple/Ops.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -11,6 +12,15 @@ {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE RankNTypes #-}+{-|+This module exports various functions that work with n-ary tuples.++Generally speaking all functions can be applied to tuples of different sizes.++However, to improve type inference we have limited our implementation to only only work on tuples of at most size 10.++For functions working with indexes we have also added some convenience functions to avoid usage of Proxy's.+-} module Data.Tuple.Ops ( -- * Selection sel@@ -31,6 +41,7 @@ , app , appPoly , appN+ , appF , mapT , mapPolyT -- ** convenience functions @@ -51,6 +62,19 @@ , reverseT , initT , tailT+ -- * Insertion+ , ins+ , insN+ , ins1+ , ins2+ , ins3+ , ins4+ , ins5+ , ins6+ , ins7+ , ins8+ , ins9+ , ins10 -- * Deletion , del , delN@@ -65,6 +89,9 @@ , del8 , del9 , del10+ -- * Folding+ , foldlT+ , foldrT -- * Currying , uncurryT , curryT) where@@ -277,6 +304,25 @@ app10 :: AppN f s 9 t => f -> s -> t app10 f s = appN f s (Proxy :: Proxy 9) +class AppF f s t | f s -> t where+ -- | Apply an n-ary function to an n-ary tuple. The function takes an argument for each component of the tuple in left-to-right order.+ --+ -- >>> appF (\a b c -> if a then b else c) (False,1,2)+ -- 2+ appF :: f -> s -> t++instance (GenericNP s rep_s, GAppF f rep_s t) => AppF f s t where+ appF f = gappF f . from_np++class GAppF f s t | f s -> t where+ gappF :: f -> s -> t++instance b ~ b' => GAppF b (NP I '[]) b' where+ gappF f Nil = f++instance (a ~ a', GAppF b (NP I xs) c) => GAppF (a -> b) (NP I (a' ': xs)) c where+ gappF f (I a :* xs) = gappF (f a) xs+ class MapT f s t | f s -> t where -- | Maps a monomorphic function over each element in an n-ary tuple that matches the type of the argument of the function --@@ -354,6 +400,85 @@ instance GSnocT a (NP I xs) (NP I xs') => GSnocT a (NP I (b ': xs)) (NP I (b ': xs')) where gsnocT a (b :* xs) = b :* gsnocT a xs +class Insert a s t where+ -- | Inserts an element into an n-ary tuple. Its position is determined by the target type+ --+ -- >>> ins 5 ('c', False) :: (Char, Integer, Bool)+ -- ('c',5,False)+ --+ -- An element will only be inserted at a specific position if:+ --+ -- * The element type matches the component type+ -- * The tail of the tuple remains well-typed+ --+ -- >>> ins 5 ('c',1,False) :: (Char, Integer, Bool, Integer)+ -- ('c',1,False,5)+ --+ -- In the above example, inserting 5 after 'c' would make the tail of the tuple have type (Integer, Bool) when the target type asks for (Bool,Integer)+ --+ -- When attempting to insert an element before or after a component of the same type the element is always inserted in front+ --+ -- >>> ins 5 ('c',1,False) :: (Char, Integer, Integer, Bool)+ -- ('c',5,1,False)+ ins :: a -> s -> t++instance (GenericNP s rep_s, GenericNP t rep_t, GInsert (InsLoc a rep_s rep_t) a rep_s rep_t) => Insert a s t where+ ins a = to_np . gins (Proxy :: Proxy (InsLoc a rep_s rep_t)) a . from_np++class GInsert loc a s t where+ gins :: Proxy loc -> a -> s -> t++instance {-# OVERLAPPING #-} GInsert Z' a (NP I xs) (NP I (a ': xs)) where+ gins _ a s = I a :* s++instance {-# OVERLAPPABLE #-} (b ~ c, GInsert n a (NP I xs) (NP I xs')) => GInsert (S' n) a (NP I (b ': xs)) (NP I (c ': xs')) where+ gins _ a (b :* xs) = b :* gins (Proxy :: Proxy n) a xs+++class InsertN a s n t | a s n -> t where+ -- | Inserts an element at an index specified position into an n-ary tuple+ --+ -- >>> insN 5 ('c',1,False) (Proxy :: Proxy 1)+ -- ('c',5,1,False)+ insN :: a -> s -> Proxy n -> t++instance (GenericNP s rep_s, GenericNP t rep_t, GInsertN a rep_s (Lit n) rep_t) => InsertN a s n t where+ insN a s p = to_np $ ginsN a (from_np s) (Proxy :: Proxy (Lit n))++class GInsertN a s n t | a s n -> t where+ ginsN :: a -> s -> Proxy n -> t++instance GInsertN a (NP I xs) Z' (NP I (a ': xs)) where+ ginsN a s _ = I a :* s++instance GInsertN a (NP I xs) n (NP I xs') => GInsertN a (NP I (b ': xs)) (S' n) (NP I (b ': xs')) where+ ginsN a (b :* s) _ = b :* ginsN a s (Proxy :: Proxy n)++-- | Inserts an element in head position into an n-ary tuple+--+-- >>> ins1 5 ('c',1,False)+-- (5,'c',1,False)+ins1 :: InsertN a s 0 t => a -> s -> t+ins1 a s = insN a s (Proxy :: Proxy 0)+ins2 :: InsertN a s 1 t => a -> s -> t+ins2 a s = insN a s (Proxy :: Proxy 1) +ins3 :: InsertN a s 2 t => a -> s -> t+ins3 a s = insN a s (Proxy :: Proxy 2) +ins4 :: InsertN a s 3 t => a -> s -> t+ins4 a s = insN a s (Proxy :: Proxy 3) +ins5 :: InsertN a s 4 t => a -> s -> t+ins5 a s = insN a s (Proxy :: Proxy 4) +ins6 :: InsertN a s 5 t => a -> s -> t+ins6 a s = insN a s (Proxy :: Proxy 5) +ins7 :: InsertN a s 6 t => a -> s -> t+ins7 a s = insN a s (Proxy :: Proxy 6) +ins8 :: InsertN a s 7 t => a -> s -> t+ins8 a s = insN a s (Proxy :: Proxy 7) +ins9 :: InsertN a s 8 t => a -> s -> t+ins9 a s = insN a s (Proxy :: Proxy 8) +ins10 :: InsertN a s 9 t => a -> s -> t+ins10 a s = insN a s (Proxy :: Proxy 9) + class Delete s t where -- | Deletes the first element in an n-ary tuple whose type does not exist in the target type --@@ -417,6 +542,47 @@ del10 :: DeleteN s 9 t => s -> t del10 s = delN s (Proxy :: Proxy 9) +class FoldLeft f s t | f s -> t where+ -- | Fold left for n-ary tuples+ --+ -- >>> foldlT (-) 0 (4,3,2,1)+ -- -10+ foldlT :: f -> t -> s -> t++instance (GenericNP s rep_s, GFoldLeft f rep_s t) => FoldLeft f s t where+ foldlT f b = gfoldlT f b . from_np++class GFoldLeft f s t | f s -> t where+ gfoldlT :: f -> t -> s -> t++instance GFoldLeft (b -> a -> b) (NP I '[]) b where+ gfoldlT f b Nil = b++instance (a ~ a', GFoldLeft (b -> a -> b) (NP I xs) b) => GFoldLeft (b -> a -> b) (NP I (a' ': xs)) b where+ gfoldlT f b (I a :* xs) = gfoldlT f (f b a) xs++class FoldRight f s t | f s -> t where+ -- | Fold right for n-ary tuples+ --+ -- >>> foldrT (-) 0 (4,3,2,1)+ -- 2+ foldrT :: f -> t -> s -> t++instance (GenericNP s rep_s, GFoldRight f rep_s t) => FoldRight f s t where+ foldrT f b = gfoldrT f b . from_np++class GFoldRight f s t | f s -> t where+ gfoldrT :: f -> t -> s -> t++instance GFoldRight (a -> b -> b) (NP I '[]) b where+ gfoldrT f b Nil = b++instance (a ~ a', b ~ b', GFoldRight (a -> b' -> b) (NP I xs) b) => GFoldRight (a -> b' -> b) (NP I (a' ': xs)) b where+ gfoldrT f b (I a :* xs) = f a $ gfoldrT f b xs++class FoldLeftF f s t | f s -> t where+ foldlF :: f -> s -> t+ -- Currently broken. So not exported until I can properly fix it. class FlattenT s t | s -> t where -- | Compresses sub-tuples into their paren-tuples@@ -594,6 +760,15 @@ poly :: (a -> b) -> Poly a b poly = Poly +type family InsLoc a s t :: Nat' where+ InsLoc a (NP I (b ': s)) (NP I (a ': t)) = If (AreEqual (NP I (b ': s)) (NP I t)) Z' (S' (InsLoc a (NP I s) (NP I t)))+ InsLoc a (NP I (b ': s)) (NP I (b ': t)) = S' (InsLoc a (NP I s) (NP I t))+ InsLoc a (NP I '[]) (NP I '[a]) = Z'++type family If b (l :: k) (r :: k) :: k where+ If 'True l r = l+ If 'False l r = r+ type family Head xs where Head (x ': xs) = x @@ -613,6 +788,11 @@ ToFun (a ': xs) f = a -> ToFun xs f ToFun '[] (a -> b) = a -> ToFun '[] b ToFun '[] b = b++type family AreEqual s t where+ AreEqual (NP I (a ': s)) (NP I (a ': t)) = AreEqual (NP I s) (NP I t)+ AreEqual (NP I (a ': s)) (NP I (b ': t)) = 'False+ AreEqual s t = 'True data Rel = Nat :<= Nat | Nat :>= Nat
tuple-sop.cabal view
@@ -5,7 +5,7 @@ -- hash: bedd24089ddeb043bac813200514481dc5863932183927ae9d7522cfe0591d55 name: tuple-sop-version: 0.3.0.0+version: 0.3.1.0 synopsis: functions on n-ary tuples using generics-sop description: Exports various functions on n-ary tuples. This library uses generics-sop to create a generic representation of n-ary product types. To regain type inference, the exported functions work only on tuples with at most 10 components. category: Data