packages feed

genifunctors 0.1.1.0 → 0.2.0.0

raw patch · 3 files changed

+131/−9 lines, 3 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Data.Generics.Genifunctors: genFoldMapT :: [(Name, Name)] -> Name -> Q Exp
+ Data.Generics.Genifunctors: genTraverseT :: [(Name, Name)] -> Name -> Q Exp

Files

Data/Generics/Genifunctors.hs view
@@ -21,7 +21,17 @@ --travU :: Applicative f => (a -> f a') -> (b -> f b') -> (c -> f c') -> (d -> f d') -> U a b c d -> f (U a' b' c' d') --travU = $(genTraverse ''U) -- @-module Data.Generics.Genifunctors (genFmap, genFoldMap, genTraverse) where+--+-- 'genFoldMapT' and 'genTraverseT' allow for specifying custom functions to handle+-- subparts of a specific type. The compiler will throw an error if any of the+-- types is actually a type synonym.+module Data.Generics.Genifunctors+  ( genFmap+  , genFoldMap+  , genFoldMapT+  , genTraverse+  , genTraverseT+  ) where  import Language.Haskell.TH import Control.Applicative@@ -42,11 +52,19 @@     }  gen :: Generator -> Name -> Q Exp-gen generator tc = do-    (fn,decls) <- evalRWST (generate tc) generator M.empty+gen g = genT g []+        +genT :: Generator -> [(Name,Name)] -> Name -> Q Exp+genT generator predef tc = do+    forM_ predef $ \(con,_) -> do+      info <- reify con+      case info of+        TyConI (TySynD{}) -> fail $ show con ++ " is a type synonym."+        TyConI _          -> return ()+        _                 -> fail $ show con ++ " is not a type constructor." +    (fn,decls) <- evalRWST (generate tc) generator $ M.fromList predef     return $ LetE decls (VarE fn) - -- | Generate generalized 'fmap' for a type -- -- @@@ -67,7 +85,20 @@ --foldMapEither = $(genFoldMap ''Either) -- @ genFoldMap :: Name -> Q Exp-genFoldMap = gen Generator+genFoldMap = genFoldMapT []++-- | Generate generalized 'foldMap' for a type, optionally traversing+--   subparts of it with custom implementations.+--+-- @+--foldTupleRev :: Monoid m => (a -> m) -> (b -> m) -> (a,b) -> m+--foldTupleRev f g (a,b) = g b <> f a+--+--foldUCustom :: Monoid m => (a -> m) -> (b -> m) -> (c -> m) -> (d -> m) -> U a b c d -> m+--foldUCustom = $(genFoldMapT [(''(,), 'foldTupleRev)] ''U)+-- @+genFoldMapT :: [(Name,Name)] -> Name -> Q Exp+genFoldMapT = genT Generator     { gen_combine   = foldMapCombine     , gen_primitive = foldMapPrimitive     , gen_type      = foldMapType@@ -80,7 +111,23 @@ --travTriple = $(genTraverse ''(,,)) -- @ genTraverse :: Name -> Q Exp-genTraverse = gen Generator+genTraverse = genTraverseT []++-- | Generate generalized 'traversable' for a type, optionally traversing+--   subparts of it with custom implementations.+--+-- @+--travTupleRev :: Applicative f => (a -> f a') -> (b -> f b') -> (a,b) -> f (a',b')+--travTupleRev f g (a,b) = (\b a -> (a,b)) <$> g b <*> f a+--+--travUCustom :: Applicative f => (a -> f a') -> (b -> f b') -> (c -> f c') -> (d -> f d') -> U a b c d -> f (U a' b' c' d')+--travUCustom = $(genTraverseT [(''(,), 'travTupleRev), (''V, 'travVCustom)] ''U)+--+--travVCustom :: Applicative f => (a -> f a') -> (b -> f b') -> V a b -> f (V a' b')+--travVCustom = $(genTraverseT [(''U, 'travUCustom)] ''V)+-- @+genTraverseT :: [(Name, Name)] -> Name -> Q Exp+genTraverseT = genT Generator     { gen_combine   = traverseCombine     , gen_primitive = traversePrimitive     , gen_type      = traverseType ''Applicative@@ -90,8 +137,8 @@ fmapCombine con_name args = foldl AppE (ConE con_name) args  foldMapCombine :: Name -> [Exp] -> Exp-foldMapCombine _con_name []     = VarE 'mempty-foldMapCombine _con_name (a:as) = foldr (<<>>) a as+foldMapCombine _con_name [] = VarE 'mempty+foldMapCombine _con_name as = foldr1 (<<>>) as  traverseCombine :: Name -> [Exp] -> Exp traverseCombine con_name []     = VarE 'pure `AppE` ConE con_name
+ Test.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE TemplateHaskell #-}+module Main where++import Data.Generics.Genifunctors+import Data.Monoid+import Control.Applicative+import System.Exit++import TestTypes++import Control.Monad.Writer++fmapU :: (a -> a') -> (b -> b') -> (c -> c') -> (d -> d') -> U a b c d -> U a' b' c' d'+fmapU = $(genFmap ''U)++foldU :: Monoid m => (a -> m) -> (b -> m) -> (c -> m) -> (d -> m) -> U a b c d -> m+foldU = $(genFoldMap ''U)++travU :: Applicative f => (a -> f a') -> (b -> f b') -> (c -> f c') -> (d -> f d') -> U a b c d -> f (U a' b' c' d')+travU = $(genTraverse ''U)++bimapTuple :: (a -> a') -> (b -> b') -> (a,b) -> (a',b')+bimapTuple = $(genFmap ''(,))++foldMapEither :: Monoid m => (a -> m) -> (b -> m) -> Either a b -> m+foldMapEither = $(genFoldMap ''Either)++travTriple :: Applicative f => (a -> f a') -> (b -> f b') -> (c -> f c') -> (a,b,c) -> f (a',b',c')+travTriple = $(genTraverse ''(,,))++foldTupleRev :: Monoid m => (a -> m) -> (b -> m) -> (a,b) -> m+foldTupleRev f g (a,b) = g b `mappend` f a++foldUCustom :: Monoid m => (a -> m) -> (b -> m) -> (c -> m) -> (d -> m) -> U a b c d -> m+foldUCustom = $(genFoldMapT [(''(,), 'foldTupleRev)] ''U)++travTupleRev :: Applicative f => (a -> f a') -> (b -> f b') -> (a,b) -> f (a',b')+travTupleRev f g (a,b) = (\b a -> (a,b)) <$> g b <*> f a++travUCustom :: Applicative f => (a -> f a') -> (b -> f b') -> (c -> f c') -> (d -> f d') -> U a b c d -> f (U a' b' c' d')+travUCustom = $(genTraverseT [(''(,), 'travTupleRev), (''V, 'travVCustom)] ''U)++travVCustom :: Applicative f => (a -> f a') -> (b -> f b') -> V a b -> f (V a' b')+travVCustom = $(genTraverseT [(''U, 'travUCustom)] ''V)++assertEq :: (Show a,Eq a) => a -> a -> IO ()+assertEq a b | a == b = return ()+assertEq a b = do+  putStrLn $ show a ++ " /=\n" ++ show b+  exitFailure++main :: IO ()+main = do+    let v = L [0 :+: 1, M (X ((Right 5) :+: 4)), M (Z (2,3)), R 6 ""]+    assertEq (fmapU (+1) (+2) (+3) (+4) v) (L [1 :+: 1, M (X ((Right 9) :+: 4)), M (Z (3,5)), R 9 ""])+    let s = (:[])+    assertEq (foldU s s s s v) ([0,5,2,3,6])+    assertEq (foldUCustom s s s s v) ([0,5,3,2,6])+    let t = tell . s+    assertEq (execWriter (travU t t t t v)) ([0,5,2,3,6])+    assertEq (execWriter (travUCustom t t t t v)) ([0,5,3,2,6])++
genifunctors.cabal view
@@ -1,5 +1,5 @@ name:                genifunctors-version:             0.1.1.0+version:             0.2.0.0 synopsis:            Generate generalized fmap, foldMap and traverse description:         Generate (derive) fmap, foldMap and traverse for Bifunctors, Trifunctors, or a functor with any arity license:             BSD3@@ -9,7 +9,13 @@ category:            Generics build-type:          Simple cabal-version:       >=1.10+homepage:            https://github.com/danr/genifunctors+bug-reports:         https://github.com/danr/genifunctors/issues +source-repository head+  type: git+  location: git://github.com/danr/genifunctors.git+ library     exposed-modules:     Data.Generics.Genifunctors     other-extensions:    TemplateHaskell, PatternGuards, RecordWildCards@@ -17,4 +23,10 @@                          template-haskell < 3,                          mtl,                          containers+    default-language:    Haskell2010++test-suite test+    type:                exitcode-stdio-1.0+    main-is:             Test.hs+    build-depends:       base, template-haskell < 3, mtl, containers     default-language:    Haskell2010