我正在学习Haskell并陷入一个奇怪的问题。 我有一个很长的表达式,我需要将它分成小表达式并记录它们。我设法解决了这一部分,但我无法理解为什么我不能为所有细节添加(Const Bool)的细节。
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)
])
我得到的错误消息:
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)])
所以当你看到(Const Bool)的部分缺失时。我做错了什么? 提前谢谢
答案 0 :(得分:5)
虽然checkValue
是递归的,但eval'
不是。{1}}。我们可以用一个较小的例子来说明这一点:
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
])
您必须以eval'
和es1
递归递归es2
。更好的是,让eval
实际上完全评估表达式:
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'))