Reputation: 63
I am learning Haskell and stacked in one weird problem. I have a long expression and I need to devide it into small expressions and log them. I've managed to solve that part but I cannot understand why I cannot add details for (Const Bool) to all details.
module MonadicInterpreterLog where
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?=))
import Control.Monad
import Control.Applicative hiding (Const)
-- Simple Boolean expressions
data Expr = Const Bool | And Expr Expr | Or Expr Expr
deriving (Eq, Show, Read)
sample1 = And (Const True) (Or (Const False) (Const True))
sample2 = And (Or (Const False) (Const True)) (And (Const False) (Const True))
eval' :: Expr -> [Expr] -> (Bool, [Expr])
eval' (Const b) es = (b, Const b : es)
eval' (And e1 e2) es = (checkValue e1 && checkValue e2, And e1 e2 : e1 : e2 : es)
eval' (Or e1 e2) es = (checkValue e1 || checkValue e2, Or e1 e2 : e1 : e2 : es)
checkValue :: Expr -> Bool
checkValue (Const b) = b
checkValue (And e1 e2) = checkValue e1 && checkValue e2
checkValue (Or e1 e2) = checkValue e1 || checkValue e2
main :: IO ()
main = do
testresults <- runTestTT tests
print testresults
testlog1, testlog2 :: [Expr]
testlog1 = [(And (Const True) (Or (Const False) (Const True))),
(Const True),
(Or (Const False) (Const True)),
(Const False),
(Const True)]
testlog2 = [(And (Or (Const False) (Const True)) (And (Const False) (Const True))),
(Or (Const False) (Const True)),
(Const False),
(Const True),
(And (Const False) (Const True)),
(Const False),
(Const True)]
-- | List of tests for 'parseScore'.
tests :: Test
tests = TestLabel "MonadicInterpreterLog" (TestList [
eval' sample1 [] ~?= (True,testlog1),
eval' sample2 [] ~?= (False,testlog2)
])
The error message I get:
MonadicInterpreterLog.hs:96
expected: (True,[And (Const True) (Or (Const False) (Const True)),Const True,Or (Const False) (Const True),Const False,Const True])
but got: (True,[And (Const True) (Or (Const False) (Const True)),Const True,Or (Const False) (Const True)])
So as you see the part for (Const Bool) is missing. What wrong am I doing? Thank you in advance
Upvotes: 2
Views: 153
Reputation: 105955
While checkValue
is recursive, eval'
isn't. We can show this with a smaller example:
true = Const True
small1 = And true $ And true $ And true true
ghci> eval' small1
(True,[
And (Const True) (And (Const True) (And (Const True) (Const True))), -- level 1
Const True, And (Const True) (And (Const True) (Const True)) -- level 2
-- other levels missing
])
You have to apply eval'
recursively on es1
and es2
. Even better, have eval
actually evaluate the expressions fully:
eval :: Expr -> (Bool, [Expr])
eval expr = case expr of
Const b -> (b, [expr])
And e1 e2 -> evalWith (&&) e1 e2
Or e1 e2 -> evalWith (||) e1 e2
where
evalWith op e1 e2 =
let (b1, es1') = eval e1
(b2, es2') = eval e2
in (b1 `op` b2, expr : (es1' ++ es2'))
Upvotes: 5