{-# 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)
travW :: Applicative f => (a -> f a') -> (b -> f b') -> W a b -> f (W a' b')
travW = $(genTraverse ''W)
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])
assertEq (execWriter (travW t t (W 3))) [3]