awaitEval in Concurrent Haskell
Colin Runciman
colin@cs.york.ac.uk
Mon, 17 Feb 2003 13:40:12 +0000
This is a multi-part message in MIME format.
--------------040603000002010004050603
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
A couple of hours ago, I wrote (in reponse to Claus Reinke's suggestion):
> Thanks for this further suggestion. A solution along these lines
> might be
> possible, but it would still be restricted ...
Actually a mild variant of Claus's proposal seems to work out
quite well. Another way to avoid the problems with types is
to use a multi-parameter type class. Little example attached.
So, thanks again Claus!
Regards
Colin R
--------------040603000002010004050603
Content-Type: text/plain;
name="test3.hs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="test3.hs"
-- A mini-experiment in concurrent data-driven assertions.
-- Colin Runciman after Claus Reinke after Andy Gill after ...
-- February 2003
import Control.Concurrent
import Char(isLower)
import System.IO.Unsafe(unsafePerformIO)
-- Each type a over which assertions are to be made is
-- encoded using a metatype b.
class Assert a b | a -> b, b -> a where
assertW :: MVar b -> a -> a
assertR :: MVar b -> a
assert :: Assert a b => String -> (a->Bool) -> a -> a
assert s p x = unsafePerformIO $ do
mv <- newEmptyMVar
forkIO $ check s p (assertR mv)
return $ assertW mv x
check :: String -> (a -> Bool) -> a -> IO ()
check s p x | p x = return ()
| otherwise = putStrLn $ "assertion failure: " ++ s
-- We can use assertions over characters, encoded as themselves.
instance Assert Char Char where
assertW mv c = unsafePerformIO $ do
putMVar mv c
return c
assertR mv = unsafePerformIO $ do
c <- takeMVar mv
return c
-- Here's the metatype encoding for lists; similar definitions
-- would be needed for other structured types.
data MetaList a = Nil
| Cons (MVar a) (MVar (MetaList a))
instance Assert a b => Assert [a] (MetaList b) where
assertW mv [] = unsafePerformIO $ do
putMVar mv Nil
return []
assertW mv (x:xs) = unsafePerformIO $ do
mvx <- newEmptyMVar
mvxs <- newEmptyMVar
putMVar mv (Cons mvx mvxs)
return (assertW mvx x : assertW mvxs xs)
assertR mv = unsafePerformIO $ do
ml <- takeMVar mv
return $ case ml of
Nil ->
[]
(Cons mvx mvxs) ->
(assertR mvx : assertR mvxs)
-- Finally, a simple example application.
singleCaseWords :: String -> Bool
singleCaseWords xs = all unmixed (words xs)
unmixed :: String -> Bool
unmixed "" = True
unmixed (c:cs) | isLower c = all isLower cs
| otherwise = not (any isLower cs)
main = do
input <- getContents
putStr (assert "single-case words" singleCaseWords input)
--------------040603000002010004050603--