{-# LANGUAGE TypeOperators #-}
module Data.Generics.Fixplate.Functor
( (:+:) (..)
, (:*:) (..)
)
where
import Prelude hiding ( foldl , foldr , mapM )
import Control.Applicative ()
import Control.Monad ( liftM )
import Data.Generics.Fixplate
data (f :+: g) a = InL (f a) | InR (g a) deriving (Eq,Ord,Show)
data (f :*: g) a = (f a) :*: (g a) deriving (Eq,Ord,Show)
infixl 6 :+:
infixl 7 :*:
instance (Functor f, Functor g) => Functor (f :+: g) where
fmap h (InL x) = InL (fmap h x)
fmap h (InR y) = InR (fmap h y)
instance (Foldable f, Foldable g) => Foldable (f :+: g) where
foldl h a (InL x) = foldl h a x
foldl h a (InR y) = foldl h a y
foldr h a (InL x) = foldr h a x
foldr h a (InR y) = foldr h a y
instance (Traversable f, Traversable g) => Traversable (f :+: g) where
traverse h (InL x) = InL <$> traverse h x
traverse h (InR y) = InR <$> traverse h y
mapM h (InL x) = liftM InL $ mapM h x
mapM h (InR y) = liftM InR $ mapM h y
instance (Functor f, Functor g) => Functor (f :*: g) where
fmap h (x :*: y) = fmap h x :*: fmap h y
instance (Foldable f, Foldable g) => Foldable (f :*: g) where
foldl h a (x :*: y) = let a' = foldl h a x in foldl h a' y
foldr h a (x :*: y) = let a' = foldr h a y in foldr h a' x
instance (Traversable f, Traversable g) => Traversable (f :*: g) where
traverse h (x :*: y) = (:*:) <$> traverse h x <*> traverse h y
mapM h (x :*: y) = do
x1 <- mapM h x
y1 <- mapM h y
return (x1 :*: y1)
app_prec , mul_prec :: Int
app_prec = 10
mul_prec = 7
instance (EqF f, EqF g) => EqF (f :+: g) where
equalF (InL x) (InL y) = equalF x y
equalF (InR x) (InR y) = equalF x y
equalF _ _ = False
instance (OrdF f, OrdF g) => OrdF (f :+: g) where
compareF (InL x) (InL y) = compareF x y
compareF (InR x) (InR y) = compareF x y
compareF (InL _) (InR _) = LT
compareF (InR _) (InL _) = GT
instance (ShowF f, ShowF g) => ShowF (f :+: g) where
showsPrecF d (InL x) = showParen (d>app_prec)
$ showString "InL "
. showsPrecF (app_prec+1) x
showsPrecF d (InR x) = showParen (d>app_prec)
$ showString "InR "
. showsPrecF (app_prec+1) x
instance (EqF f, EqF g) => EqF (f :*: g) where
equalF (x1 :*: x2) (y1 :*: y2) = equalF x1 y1 && equalF x2 y2
instance (OrdF f, OrdF g) => OrdF (f :*: g) where
compareF (x1 :*: x2) (y1 :*: y2) = case compareF x1 y1 of
LT -> LT
GT -> GT
EQ -> compareF x2 y2
instance (ShowF f, ShowF g) => ShowF (f :*: g) where
showsPrecF d (x :*: y) = showParen (d>mul_prec)
$ showsPrecF (mul_prec+1) x
. showString " :*: "
. showsPrecF (mul_prec+1) y