Assuming this function is given:
assertBool :: String -> Bool -> IO ()
...
My first stab would be:
assertBool1 :: IO [a] -> IO [a] -> ([a] -> [a] -> Bool) -> IO () assertBool1 f1 f2 comp = do a1 <- f1 a2 <- f2 assertBool "fail" $ comp a1 a2
Then your main code could be:
assertBool1 (someFunc a) (someFunc b) (==)
...
So far so good, maybe? But what happens if the values you want to test are not lists? The assertBool1 could be generalized somewhat:
assertBool2 :: IO a -> IO b -> (a -> b -> Bool) -> IO () assertBool2 fa fb comp = do va <- fa vb <- fb assertBool "fail" $ comp va vb
(All that's really changed here is the type signature)
...
But what if you want a test that uses just one value, or three, or more? At this point I think you start having to use the liftM variants, but others may have better ideas. It may be that the lifting can be hidden in auxiliiarty function/operator definitions; e.g. see the Haskell library function Monad.ap for possible clues.
...
Anyway, here's some complete code, tested under Hugs: [[ import Monad( unless )
assertBool :: String -> Bool -> IO () assertBool err bool = unless bool (error err)
someFunc :: String -> IO String someFunc s = return s
assertBool1 :: IO [a] -> IO [a] -> ([a] -> [a] -> Bool) -> IO () assertBool1 f1 f2 comp = do a1 <- f1 a2 <- f2 assertBool "fail" $ comp a1 a2
test1 :: String -> String -> IO () test1 a b = do { assertBool1 (someFunc a) (someFunc b) (==) ; putStrLn "test1 OK" } -- test1 "a" "a" -> "test1 OK" -- test1 "a" "b" -> "fail"
assertBool2 :: IO a -> IO b -> (a -> b -> Bool) -> IO () assertBool2 fa fb comp = do va <- fa vb <- fb assertBool "fail" $ comp va vb
test2 :: String -> String -> IO () test2 a b = do { assertBool1 (someFunc a) (someFunc b) (==) ; putStrLn "test2 OK" } -- test2 "a" "a" -> "test2 OK" -- test2 "a" "b" -> "fail" ]]
#g --
At 10:29 23/03/04 -0500, Sean E. Russell wrote:
Hello,
I posted this question to comp.lang.functional, and someone suggested that I try this group instead.
I'm struggling with monads. Well, not monads themselves, but mixing them with
non-monadic functions.
Here's my base case:
someFunc :: String -> IO [a] ... ax <- someFunc a bx <- someFunc b assertBool "fail" $ length ax == length bx
I don't like the assignments; the typing is redundant, if I have a lot of asserts like this, and the "variables" are temporary. What I'd much rather have is:
...
assertBool "fail" $ (length $ someFunc a) == (length $ someFunc b)
which is more readable, to my eye.
The only solution which has been suggested that may work is liberal use of the
liftM variants, but this gets *really* tedious and obtuse.
Is there an elegant way to do what I want to do, or am I stuck with procedural-style assignments and bunches of temp vars?
Thanks!
-- ### SER ### Deutsch|Esperanto|Francaise|Linux|XML|Java|Ruby|Aikido ### http://www.germane-software.com/~ser jabber.com:ser ICQ:83578737 ### GPG: http://www.germane-software.com/~ser/Security/ser_public.gpg _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
_______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell