further simplified from ~/svn/MagicHaskeller/allifdefs/FMType.lhs
\begin{code}
module MagicHaskeller.FMType(FMType(..), updateFMT, unionFMT, unitFMT, lookupFMT, fmtToList, eltsFMT,
mapFMT
) where
import MagicHaskeller.Types
import Data.IntMap as IM
import Data.Monoid
data FMType a = EmptyFMT
| FMT {
tvFMT :: IntMap a,
tcFMT :: IntMap a,
taFMT :: (FMType (FMType a)),
fnFMT :: (FMType (FMType a)),
funFMT :: (FMType (FMType a))
}
deriving (Read, Show)
lookupFMT :: Type -> FMType a -> Maybe a
lookupFMT _ EmptyFMT = Nothing
lookupFMT (TV tv) fmt = IM.lookup (fromIntegral tv) (tvFMT fmt)
lookupFMT (TC tc) fmt = IM.lookup (fromIntegral tc) (tcFMT fmt)
lookupFMT (TA t0 t1) fmt = lookupFMTFMT t0 t1 (taFMT fmt)
#ifdef RIGHTFMT
lookupFMT (t0 :> t1) fmt = lookupFMTFMT t0 t1 (fnFMT fmt)
lookupFMT (t0 :-> t1) fmt = lookupFMTFMT t0 t1 (funFMT fmt)
#else
lookupFMT (t1 :> t0) fmt = lookupFMTFMT t0 t1 (fnFMT fmt)
lookupFMT (t1 :-> t0) fmt = lookupFMTFMT t0 t1 (funFMT fmt)
#endif
lookupFMTFMT t0 t1 fmtfmt = lookupFMT t0 fmtfmt >>= lookupFMT t1
mapFMT :: (Type -> a -> b) -> FMType a -> FMType b
mapFMT f EmptyFMT = EmptyFMT
mapFMT f (FMT v c a n u) = FMT (mapWithKey (\tv -> f (TV $ fromIntegral tv)) v)
(mapWithKey (\tc -> f (TC $ fromIntegral tc)) c)
(mapFMT (\t0 -> mapFMT (\t1 -> f (TA t0 t1))) a)
(mapFMT (\t0 -> mapFMT (\t1 -> f (t1 :> t0))) n)
(mapFMT (\t0 -> mapFMT (\t1 -> f (t1 :-> t0))) u)
eltsFMT :: FMType a -> [a]
eltsFMT EmptyFMT = []
eltsFMT (FMT vs cs as fs fus) = elems vs ++ elems cs ++ [ x | fmt <- eltsFMT as, x <- eltsFMT fmt ] ++ [ x | fmt <- eltsFMT fs, x <- eltsFMT fmt ] ++ [ x | fmt <- eltsFMT fus, x <- eltsFMT fmt ]
fmtToList :: FMType a -> [(Type,a)]
fmtToList EmptyFMT = []
fmtToList (FMT vs cs as fs fus) = fmToTypedVars vs ++ fmToTypedCons cs ++ [ (TA t0 t1, x) | (t0, fmt) <- fmtToList as, (t1,x) <- fmtToList fmt ] ++ [ (t1 :> t0, x) | (t0,fmt) <- fmtToList fs, (t1,x) <- fmtToList fmt ] ++ [ (t1 :-> t0, x) | (t0,fmt) <- fmtToList fus, (t1,x) <- fmtToList fmt ]
fmToTypedVars fm = Prelude.map (\ (tv,x) -> (TV $ fromIntegral tv, x)) (toList fm)
fmToTypedCons fm = Prelude.map (\ (tc,x) -> (TC $ fromIntegral tc, x)) (toList fm)
updateFMT :: (a->a) -> a -> Type -> (FMType a) -> FMType a
updateFMT f x t fmt = updFMT t fmt
where updFMT t EmptyFMT = updFMT t (FMT empty empty EmptyFMT EmptyFMT EmptyFMT)
updFMT (TV gen) fmt = fmt{tvFMT = insertWith (\_new old -> f old) (fromIntegral gen) x (tvFMT fmt)}
updFMT (TC con) fmt = fmt{tcFMT = insertWith (\_new old -> f old) (fromIntegral con) x (tcFMT fmt)}
updFMT (TA t0 t1) fmt = fmt{taFMT = updateFMT updFMTt1 (updFMTt1 EmptyFMT) t0 (taFMT fmt)}
where updFMTt1 = updFMT t1
updFMT (t0 :> t1) fmt = fmt{fnFMT = updateFMT updFMTt0 (updFMTt0 EmptyFMT) t1 (fnFMT fmt)}
where updFMTt0 = updFMT t0
updFMT (t0 :-> t1) fmt = fmt{funFMT = updateFMT updFMTt0 (updFMTt0 EmptyFMT) t1 (funFMT fmt)}
where updFMTt0 = updFMT t0
unitFMT x t = updateFMT undefined x t EmptyFMT
instance Monoid a => Monoid (FMType a) where
mappend = unionFMT mappend
mempty = EmptyFMT
unionFMT :: (a->a->a) -> FMType a -> FMType a -> FMType a
unionFMT f l r = uFMT l r
where uFMT EmptyFMT fmt = fmt
uFMT fmt EmptyFMT = fmt
uFMT (FMT vl cl al nl ul) (FMT vr cr ar nr ur) = FMT (unionWith f vl vr) (unionWith f cl cr) (unionFMT uFMT al ar) (unionFMT uFMT nl nr) (unionFMT uFMT ul ur)
\end{code}