簡體   English   中英

如何使用沒有案例的警衛重寫這個Haskell?

[英]How can I rewrite this Haskell using guards with no case-of?

我有三個版本的功能,如下所示。 #2和#3工作。 #2現在是我的第一選擇。 我想找到一些讓#1工作的方法,看看它是如何比較的。 它在底部。

首先,我有這種類型:

data Value =
    IntVal Int
  | BoolVal Bool
  deriving (Show)

而這個(工作片段)功能:

-- #2
evaluate (If ec et ef) s0 =
  case vc of
    (IntVal ____) -> error "Conditional expression in If statement must be a boolean" 
    (BoolVal vcb) -> if vcb then (vt, st)
                            else (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

我想知道我是否可以擺脫案件陳述並使用警衛代替。 我可以使用case語句后衛,我發現這工作:

-- #3
evaluate (If ec et ef) s0 =
  case vc of
    (IntVal _) -> error "Conditional expression in If statement must be a boolean" 
    (BoolVal vcb) | vcb       -> (vt, st)
                  | otherwise -> (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

很高興知道。 我認為#2最清楚地傳達了我的意圖。 盡管如此,這是我嘗試的第一件事,我想弄清楚它是如何實際工作的:

-- #1
evaluate (If ec et ef) s0 
  | (IntVal vc) = error "Conditional expression in If statement must be a boolean" 
  | vc == True  = (vt, st)
  | otherwise   = (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

這給出了以下錯誤。 似乎我需要一些東西來詢問Value類型的某些東西是否也是IntVal子類型的東西?:

Couldn't match expected type `Int' with actual type `Value'
In the first argument of `IntVal', namely `vc'
In the expression: (IntVal vc)

--------------------------------------------------------------------------------

Couldn't match expected type `Bool' with actual type `Value'
In the expression: (IntVal vc)
In a stmt of a pattern guard for
               an equation for `evaluate':
  (IntVal vc)

如何解決這些錯誤並實現無案例,僅限警衛的實施?

這不是一個真正的答案,但我會寫下這樣的事情:

evaluate (If ec et ef) s0 =
    case evaluate ec s0 of
    (True,  sc) -> evaluate et sc
    (False, sc) -> evaluate ef sc

我發現vtstvfsf的命名更難以閱讀,因為我必須自己跟蹤這些變量的數據流。 保持他們的匿名簡化了理解。

你的#1的問題在於,普通的守衛只能是布爾表達式,它們無法簡潔地匹配模式。 所以IntVal vc就不會像一個人一樣工作。 而且即使這樣做了, vc你從得到IntVal vc模式不能被用作一個Bool值-你需要的BoolVal vc該模式。

但是,您可以使用圖案保護

evaluate (If ec et ef) s0
  | IntVal _      <- vc = error "Conditional expression in If statement must be a boolean" 
  | BoolVal True  <- vc = (vt, st)
  | BoolVal False <- vc = (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

如果使用記錄語法重新定義類型Value

data Value = IntVal { unInt :: Int } | BoolVal { unBool :: Bool }

然后你可以這樣做:

evaluate (If ec et ef) s0 =
  if unBool vc then (vt, st) else (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM