2016-07-14 85 views
2

我正在学习Haskell并堆积在一个奇怪的问题。 我有一个很长的表达式,我需要将它分解成小表达式并记录下来。我已经设法解决这个部分,但我不明白为什么我不能为(Const Bool)添加细节到所有细节。Haskell函数构造

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)]) 

所以你看到的(常量布尔)的部分缺失。我在做什么错? 提前致谢

+0

这与此无关,但您应该将'Const'重新命名为其他名称。 'Control.Applicative'中有一种非常流行的类型,它看起来像'newtype Const a b = Const {getConst :: a}'。重用这个名字很可能会让人们感到困惑。一个选项可能是“Lit”,因为“文字”。 – dfeuer

+0

您最终将了解'Writer'类型,它很整齐地解决了这个问题。 – dfeuer

+0

这些条件已经在任务中设置,这就是为什么我想用预定条件解决任务的原因。 –

回答

5

虽然checkValue是递归的,但是eval'不是。我们可以用一个小例子证明这一点:

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'es1es2。更妙的是,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')) 
+0

我明白了!谢谢 –