packages feed

vinyl 0.6.0 → 0.7.0

raw patch · 4 files changed

+167/−19 lines, 4 files

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.7.0+- Simplified `match`+- Added `Data.Vinyl.Curry`+ # 0.6.0  Added a `CoRec` (co-record) type constructed in the same style as the existing `Rec` type for records. A `CoRec` is an open sum type: a value of `CoRec [a,b,c]` is either an `a`, a `b`, *or* a `c`. In contrast a `Rec [a,b,c]` includes an `a`, a `b`, *and*, a `c`.
Data/Vinyl/CoRec.hs view
@@ -156,9 +156,8 @@ asA             :: (t ∈ ts, RecApplicative ts) => proxy t -> CoRec Identity ts -> Maybe t asA p c@(CoRec _) = rget p $ coRecToRec' c --- | Pattern match on a CoRec by specifying handlers for each case. If the--- CoRec is non-empty this function is total. Note that the order of the--- Handlers has to match the type level list (t:ts).+-- | Pattern match on a CoRec by specifying handlers for each case. Note that+-- the order of the Handlers has to match the type level list (t:ts). -- -- >>> :{ -- let testCoRec = Col (Identity False) :: CoRec Identity [Int, String, Bool] in@@ -169,21 +168,8 @@ --    :& RNil -- :} -- "my Bool is not: True thus it is False"-match      :: RecApplicative (t ': ts)-           => CoRec Identity (t ': ts) -> Handlers (t ': ts) b -> b-match c hs = fromJust $ match' c hs-           -- Since we require 'ts' both for the Handlers and the CoRec, Handlers-           -- effectively defines a total function. Hence, we can safely use fromJust---- | Pattern match on a CoRec by specifying handlers for each case. The only case--- in which this can produce a Nothing is if the list ts is empty.-match'      :: RecApplicative ts => CoRec Identity ts -> Handlers ts b -> Maybe b-match' c hs = match'' hs $ coRecToRec' c-  where-    match''                             :: Handlers ts b -> Rec Maybe ts -> Maybe b-    match'' RNil        RNil            = Nothing-    match'' (H f :& _)  (Just x  :& _)  = Just $ f x-    match'' (H _ :& fs) (Nothing :& c') = match'' fs c'+match :: CoRec Identity ts -> Handlers ts b -> b+match (CoRec (Identity t)) hs = case rget Proxy hs of H f -> f t  -- | Helper for handling a variant of a 'CoRec': either the function -- is applied to the variant or the type of the 'CoRec' is refined to
+ Data/Vinyl/Curry.hs view
@@ -0,0 +1,157 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}++{-|++Provides combinators for currying and uncurrying functions over arbitrary vinyl+records.++-}+module Data.Vinyl.Curry where++import           Data.Vinyl+import           Data.Vinyl.Functor++-- * Currying++class RecordCurry ts where+  {-|+  N-ary version of 'curry' over functorial records.++  Example specialized signatures:++  @+  rcurry :: (Rec Maybe '[Int, Double] -> Bool) -> Maybe Int -> Maybe Double -> Bool+  rcurry :: (Rec (Either Int) '[Double, String, ()] -> Int) -> Either Int Double -> Either Int String -> Either Int () -> Int+  rcurry :: (Rec f '[] -> Bool) -> Bool+  @++  -}+  rcurry :: (Rec f ts -> a) -> CurriedF f ts a++  {-|+  N-ary version of 'curry' over pure records.++  Example specialized signatures:++  @+  rcurry' :: (Rec Identity '[Int, Double] -> Bool) -> Int -> Double -> Bool+  rcurry' :: (Rec Identity '[Double, String, ()] -> Int) -> Double -> String -> () -> Int+  rcurry' :: (Rec Identity '[] -> Bool) -> Bool+  @++  -}+  rcurry' :: (Rec Identity ts -> a) -> Curried ts a+++instance RecordCurry '[] where+  rcurry f = f RNil+  {-# INLINABLE rcurry #-}+  rcurry' f = f RNil+  {-# INLINABLE rcurry' #-}++instance RecordCurry ts => RecordCurry (t ': ts) where+  rcurry f x = rcurry (\xs -> f (x :& xs))+  {-# INLINABLE rcurry #-}+  rcurry' f x = rcurry' (\xs -> f (Identity x :& xs))+  {-# INLINABLE rcurry' #-}++-- * Uncurrying++{-|+N-ary version of 'uncurry' over functorial records.++Example specialized signatures:++@+runcurry :: (Maybe Int -> Maybe Double -> String) -> Rec Maybe '[Int, Double] -> String+runcurry :: (IO FilePath -> String) -> Rec IO '[FilePath] -> String+runcurry :: Int -> Rec f '[] -> Int+@+-}+runcurry :: CurriedF f ts a -> Rec f ts -> a+runcurry x RNil      = x+runcurry f (x :& xs) = runcurry (f x) xs+{-# INLINABLE runcurry #-}+++{-|+N-ary version of 'uncurry' over pure records.++Example specialized signatures:++@+runcurry' :: (Int -> Double -> String) -> Rec Identity '[Int, Double] -> String+runcurry' :: Int -> Rec Identity '[] -> Int+@++Example usage:++@+f :: Rec Identity '[Bool, Int, Double] -> Either Int Double+f = runcurry' $ \b x y -> if b then Left x else Right y+@+-}+runcurry' :: Curried ts a -> Rec Identity ts -> a+runcurry' x RNil               = x+runcurry' f (Identity x :& xs) = runcurry' (f x) xs+{-# INLINABLE runcurry' #-}++-- * Applicative Combinators++{-|+Lift an N-ary function to work over a record of 'Applicative' computations.++>>> runcurryA' (+) (Just 2 :& Just 3 :& RNil)+Just 5++>>> runcurryA' (+) (Nothing :& Just 3 :& RNil)+Nothing+-}+runcurryA' :: (Applicative f) => Curried ts a -> Rec f ts -> f a+runcurryA' f = fmap (runcurry' f) . rtraverse (fmap Identity)+{-# INLINE runcurryA' #-}++{-|+Lift an N-ary function over types in @g@ to work over a record of 'Compose'd+'Applicative' computations. A more general version of 'runcurryA''.++Example specialized signatures:++@+runcurryA :: (g x -> g y -> a) -> Rec (Compose Maybe g) '[x, y] -> Maybe a+@+-}+runcurryA :: (Applicative f) => CurriedF g ts a -> Rec (Compose f g) ts -> f a+runcurryA f = fmap (runcurry f) . rtraverse getCompose+{-# INLINE runcurryA #-}++-- * Curried Function Types++{-|+For the list of types @ts@, @'Curried' ts a@ is a curried function type from+arguments of types in @ts@ to a result of type @a@.++>>> :kind! Curried '[Int, Bool, String] Int+Curried '[Int, Bool, String] Int :: *+= Int -> Bool -> [Char] -> Int+-}+type family Curried ts a where+  Curried '[] a = a+  Curried (t ': ts) a = t -> Curried ts a+++{-|+For the type-level list @ts@, @'CurriedF' f ts a@ is a curried function type+from arguments of type @f t@ for @t@ in @ts@, to a result of type @a@.++>>> :kind! CurriedF Maybe '[Int, Bool, String] Int+CurriedF Maybe '[Int, Bool, String] Int :: *+= Maybe Int -> Maybe Bool -> Maybe [Char] -> Int+-}+type family CurriedF (f :: u -> *) (ts :: [u]) a where+  CurriedF f '[] a = a+  CurriedF f (t ': ts) a = f t -> CurriedF f ts a
vinyl.cabal view
@@ -1,5 +1,5 @@ name:                vinyl-version:             0.6.0+version:             0.7.0 synopsis:            Extensible Records -- description: license:             MIT@@ -25,6 +25,7 @@                      , Data.Vinyl.Class.Method                      , Data.Vinyl.Core                      , Data.Vinyl.CoRec+                     , Data.Vinyl.Curry                      , Data.Vinyl.Lens                      , Data.Vinyl.Derived                      , Data.Vinyl.TypeLevel