2016-07-14 79 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

我明白了!謝謝 –