HaRe-0.6: tools/base/TC/InferenceMonad.hs
-- $Id: InferenceMonad.hs,v 1.6 2001/03/28 22:08:56 sheard Exp $
module InferenceMonad where
import ST
data Value g b = Good g | Bad b deriving (Show, Eq)
newtype IM a e x = Ck (Int -> (ST a (Value x e, String, Int)))
instance Functor (IM a e) where
fmap f (Ck g) = Ck h
where h n = do { (x, out, n') <- g n
; case x of
Good a -> return (Good (f a), out, n')
Bad w -> return (Bad w, out, n')
}
instance Monad (IM a t) where
return x = Ck h
where h n = return (Good x, "", n)
(Ck g) >>= f = Ck ff
where ff n = do { (x, out1, n1) <- g n
; case x of
Good a -> let (Ck h) = f a
in do { (y, out2, n2) <- h n1
; return (y, out1 ++ out2, n2)
}
Bad b -> return (Bad b, out1, n1)
}
---- Non standard morphisms for IM monad ----------------
----- First Mutable vars ----------------------
readVar :: STRef a b -> IM a c b
newRef :: a -> IM b c (STRef b a)
writeVar :: STRef a b -> b -> IM a c ()
readVar ref = Ck f
where f n = do { z <- readSTRef ref
; return (Good z, "", n)
}
newRef init = Ck f
where f n = do { z <- newSTRef init
; return (Good z, "", n)
}
writeVar ref value = Ck f
where f n = do { z <- writeSTRef ref value
; return (Good z, "", n)
}
nextN = Ck f
where f n = return (Good n, "", n+1)
------------- Then printing and error handling -----------
printS s = Ck f
where f n = return (Good (), s, n)
pr :: Show a => [Char] -> a -> IM b c ()
pr s x = printS (s ++ (show x) ++ " -\n")
raise :: a -> IM b a c
raise err = Ck f
where f n = return (Bad err, "", n)
handle :: IM a b c -> (b -> IM a b c) -> IM a b c
handle (Ck m) f = Ck h
where h n = do { (x, out1, n') <- m n
; case x of
Good y -> return (x, out1, n')
Bad y -> let Ck a = f y
in do { (b, out2, m) <- a n'
; return (b, out1 ++ out2, m)
}
}
-------------- Finally the run function for the monad --------------
runIM :: (forall a . IM a e c) -> Int -> (Value c e,String,Int)
runIM w n = let (Ck f) = w in runST (f n)
force :: (forall a . IM a e c) -> c
force w =
case (runIM w) 0 of
(Good x, _, _) -> x
(Bad x, s, _) -> error ("error in Inference monad: " ++ s)
display :: Show c => (forall a . IM a e c) -> String
display a =
case (runIM (do { x <- a ; pr "" x })) 0 of
(_, s, _) -> s
perform :: Show a => (forall c. IM c a String) -> IO ()
perform x =
case runIM x 0 of
(Good x,message,n) -> do { putStrLn ("Good\n"++message); putStrLn"\n--------------\n"
; putStrLn x }
(Bad y, message,n) -> do { putStrLn ("Bad\n"++message); putStrLn"\n--------------\n"
; putStrLn (show y) }