happstack-contrib-0.2.1: src/Happstack/Contrib/HList.hs
{-# LANGUAGE TemplateHaskell, FlexibleInstances,
UndecidableInstances, OverlappingInstances,
MultiParamTypeClasses, CPP, FunctionalDependencies #-}
module Happstack.Contrib.HList (HasT, hlextract, hlupdate, (.&.),
(:&:),
Couple(..),Nil(..),CoupleClass,hMap,trans) where
-- HList useful with generic
import Happstack.Data.Xml
import Happstack.Data.Pairs
import Data.Generics as G
import Happstack.Contrib.HListBase
infixr 6 .&.
(.&.) :: a -> b -> Couple a b
(.&.) = Couple
type a :&: b = Couple b a
class CoupleClass a where
toPairs' :: a -> Pairs
fromPairs' :: Pairs -> Maybe a
instance (Eq a,Xml a, Show a, G.Data a,CoupleClass b) => CoupleClass (Couple a b) where
toPairs' (Couple a b) = (toPairs a) ++ (toPairs' b)
fromPairs' = const Nothing --doesn't make sense to unmix to make toPairs' . fromPairs' an identity
instance CoupleClass Nil where
toPairs' _ = []
fromPairs' _ = return Nil
instance (Xml a, Xml b) => Xml (Couple a b) where
toXml (Couple a b) = (toXml a) ++ (toXml b)
readXml r xml = do
(xml', a) <- readXml r xml
(xml'', b) <- readXml r xml'
return (xml'', Couple a b)
hlextract :: HasT a b => a -> b
hlextract = x
hlupdate :: HasT a b => a -> b -> a
hlupdate = u
class HasT a b where
x :: a -> b
u :: a -> b -> a
instance HasT (Couple a b) a where
x (Couple a _) = a
u (Couple _ b) a = Couple a b
instance HasT (Couple a b) b where
x (Couple _ b) = b
u (Couple a _) b = Couple a b
-- Oleg's trick http://www.haskell.org/pipermail/haskell/2004-June/014176.html
class HasT' a b where
x' :: a -> b
u' :: a -> b -> a
instance HasT' a b => HasT a b where
x = x'
u = u'
instance (HasT c a) => HasT' (Couple b c) a where
x' (Couple _ b) = x b
u' (Couple a b) c = Couple a (u b c)
class Trans ft a where
trans :: ft -> a -> a
instance Trans (a->a) (Couple a b) where
trans f (Couple a b) = Couple (f a) b
instance Trans (b->b) (Couple a b) where
trans f (Couple a b) = Couple a (f b)
class Trans' ft a where
trans' :: ft -> a ->a
instance Trans' ft a => Trans ft a where
trans = trans'
instance (Trans ft b) => Trans' ft (Couple a b) where
trans' f (Couple a b) = Couple a (trans f b)
class HMap a b | a -> b where
hMap::a->b
instance (HMap b d,CoupleClass b) => HMap (Couple a b) (Couple [a] d) where
hMap (Couple a b) = Couple [a] $ hMap b
instance HMap (Couple a Nil) (Couple [a] Nil) where
hMap (Couple a Nil) = Couple [a] Nil