{-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleInstances #-} module LeftRight where import Control.Monad import Base import TEq import Repr -- * Generation of left/right values -- Ugly implementation for now. -- Should be improved! class LR (f :: (* -> *) -> (* -> *) -> * -> *) s where leftf :: s ix -> (forall ix . Ix s ix => s ix -> r ix) -> [f s r ix] rightf :: s ix -> (forall ix . Ix s ix => s ix -> r ix) -> [f s r ix] instance (LR a s,LR b s) => LR (a :+: b) s where leftf w f = map L (leftf w f) ++ map R (leftf w f) rightf w f = map R (rightf w f) ++ map L (rightf w f) instance (LR a s, LR b s) => LR (a :*: b) s where leftf w f = zipWith (:*:) (leftf w f) (leftf w f) rightf w f = zipWith (:*:) (rightf w f) (rightf w f) instance Ix s ixr => LR (I ixr) s where leftf _ f = [I (f index)] rightf _ f = [I (f index)] instance LRA a => LR (K a) s where leftf w f = [K lefta] rightf w f = [K righta] class LRA a where lefta :: a righta :: a {- - This should be more efficient (compile time checking of Tag ls) instance (Zero (f r s ix)) => LR (Tag ix f r s ix) where left = [Tag zero] right = [Tag zero] instance LR (Tag ix' f r s ix) where left = [] right = [] -} -- The instance below can be used when no undecidable instances are desired. -- In that case type comparisons are carried out at runtime instance (Repr s,Ix s ixt,LR f s) => LR (f :>: ixt) s where leftf w f = case ixeq (index::s ixt) w of Nothing -> [] Just Refl -> map Tag (leftf w f) rightf w f = case ixeq (index::s ixt) w of Nothing -> [] Just Refl -> map Tag (rightf w f) -- Ad-hoc left/right 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 -- Not very good for distinguishing constructors instance LRA () where lefta = () righta = () safeHead [] = error "Internal error, left or right returned []" safeHead (x:xs) = x left :: (Ix s ix, LR (PF s) s) => s ix -> ix left w = to $ safeHead $ leftf w (I0 . left) right :: (Ix s ix, LR (PF s) s) => s ix -> ix right w = to $ safeHead $ rightf w (I0 . right)