{-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Generics.MultiRec.Rewriting.LeftRight -- Copyright : (c) 2009 Universiteit Utrecht -- License : BSD3 -- -- Maintainer : generics@haskell.org -- Stability : experimental -- Portability : non-portable -- -- Summary: This module defines two functions, left and right, which should -- produce different values. ----------------------------------------------------------------------------- module Generics.MultiRec.Rewriting.LeftRight ( Single, singlef , left, right ) where import Generics.MultiRec.Base -- * Generation of left/right values class Single (s :: * -> *) (f :: (* -> *) -> * -> *) where singlef :: s ix -> (forall ix'. Fam s => s ix' -> r ix') -> Bool -> [f r ix] instance (Single s a, Single s b) => Single s (a :+: b) where singlef w f True = map L (singlef w f True ) ++ map R (singlef w f True) singlef w f False = map R (singlef w f False) ++ map L (singlef w f False) instance (Single s a) => Single s (C c a) where singlef w f b = map C (singlef w f b) instance (Single s a, Single s b) => Single s (a :*: b) where singlef w f b = zipWith (:*:) (singlef w f b) (singlef w f b) instance (Fam s, El s ixr) => Single s (I ixr) where singlef _ f _ = [I (f proof)] instance LRA a => Single s (K a) where singlef _ _ True = [K lefta] singlef _ _ False = [K righta] instance Single s U where singlef _ _ _ = [U] instance (EqS s, El s ixt, Single s f) => Single s (f :>: ixt) where singlef w f b = case eqS (proof :: s ixt) w of Nothing -> [] Just Refl -> map Tag (singlef w f b) -- * Ad-hoc left/right (for types outside the family) class LRA a where lefta :: a righta :: a instance LRA Char where lefta = 'L' righta = 'R' instance LRA a => LRA [a] where lefta = [] righta = [righta] instance LRA Int where lefta = 0 righta = 1 instance LRA Integer where lefta = 0 righta = 1 -- Nothing better can be done here... instance LRA () where lefta = () righta = () safeHead :: [a] -> a safeHead [] = error "Internal error, left or right returned []" safeHead (x:_) = x left :: (Fam s, Single s (PF s)) => s ix -> ix left w = to w . safeHead $ singlef w (I0 . left) True right :: (Fam s, Single s (PF s)) => s ix -> ix right w = to w . safeHead $ singlef w (I0 . right) False