-- -- (c) Susumu Katayama -- \begin{code} {-# OPTIONS -cpp #-} module MagicHaskeller.DebMT where import MagicHaskeller.Types as Types import MagicHaskeller.TyConLib import Control.Monad -- import CoreLang import Control.Monad.Search.Combinatorial import MagicHaskeller.PriorSubsts import Data.Array import MagicHaskeller.T10((!?)) import Data.List(genericIndex) import System.IO.Unsafe(unsafeInterleaveIO) -- type MemoTrie = MapType (Matrix Possibility) type Possibility e = (Bag e, Subst, TyVar) data MapType a = MT { tvMT :: [a], tcMT :: [a], genMT :: [a], -- "forall" stuff taMT :: MapType (MapType a), funMT :: MapType (MapType a) } lookupMT :: MapType a -> Type -> a -- lookupMT :: MonadPlus m => MapType (m a) -> Type -> (m a) lookupMT mt (TV tv) = tvMT mt `genericIndex` tv lookupMT mt (TC tc) | tc < 0 = genMT mt `genericIndex` (-1-tc) | otherwise = tcMT mt `genericIndex` tc lookupMT mt (TA t0 t1) = lookupMT (lookupMT (taMT mt) t0) t1 lookupMT mt (t0:->t1) = lookupMT (lookupMT (funMT mt) t0) t1 retrieve :: Decoder -> Subst -> Subst -- retrieve deco sub = let news = [ (decodeVar deco i, decode deco ty) | (i, ty) <- sub ] in trace ("sub = " ++ show sub ++ " and news = " ++ show news ++ " and deco = " ++ show deco) news retrieve deco sub = [ (decodeVar deco i, decode deco ty) | (i, ty) <- sub ] decode :: Decoder -> Type -> Type decode deco t = mapTV (decodeVar deco) t decodeVar (Dec tvs margin) tv = case tvs !? tv of Nothing -> tv+margin Just ntv -> ntv encode :: Type -> TyVar -> (Type, Decoder) encode = Types.normalizeVarIDs mkMT :: TyConLib -> (Type->a) -> MapType a mkMT tcl f = mkMT' tcl 0 f mkMT' :: TyConLib -> Kind -> (Type->a) -> MapType a mkMT' tcl k f = MT tvTree tcTree genTree taTree funTree where tcs = snd tcl ! k tvTree = [ f (TV i) | i <- [0..] ] tcTree = [ f (TC i) | i <- [0..] ] genTree = [ f (TC i) | i <- [-1,-2..] ] taTree = mkMT' tcl (k+1) (\t0 -> mkMT tcl (\t1 -> f (TA t0 t1))) funTree = if k==0 then mkMT tcl (\t0 -> mkMT tcl (\t1 -> f (t0 :-> t1))) else error "mkMT': the kind of functions must always be *" mkMTIO :: TyConLib -> (Type -> IO a) -> IO (MapType a) mkMTIO tcl f = mkMTIO' tcl 0 f mkMTIO' :: TyConLib -> Kind -> (Type -> IO a) -> IO (MapType a) -- IOのところはMonad m => mでよさそう.実際にはMonadIOでやるかも. mkMTIO' tcl k f = unsafeInterleaveIO $ liftM5 MT tvTree tcTree genTree taTree funTree where tcs = snd tcl ! k lazyf = unsafeInterleaveIO . f tvTree = interleaveActions $ map (f . TV) [0..] tcTree = interleaveActions $ map (f . TC) [0..] genTree = interleaveActions $ map (f . TC) [-1,-2..] taTree = mkMTIO' tcl (k+1) (\t0 -> mkMTIO tcl (\t1 -> lazyf (TA t0 t1))) funTree = mkMTIO tcl $ if k==0 then (\t0 -> mkMTIO tcl (\t1 -> lazyf (t0 :-> t1))) else error "mkMTIO': the kind of functions must always be *" -- funTree = if k==0 then mkMTIO tcl (\t0 -> mkMTIO tcl (\t1 -> lazyf (t0 :-> t1))) else error "mkMTIO': the kind of functions must always be *" -- これは間違い.一番外側にunsafeInterleaveIOがないと,kindが0でないinvalidな関数の型も作ろうとしてしまう. -- I do not add unsafe because I do not understand in what sense unsafeInterleaveIO is unsafe! interleaveActions :: [IO a] -> IO [a] interleaveActions = foldr (\x xs -> unsafeInterleaveIO (Control.Monad.liftM2 (:) x xs)) (return []) . map unsafeInterleaveIO \end{code}