![](/img/trans.png)
[英]Is it possible to rewrite this Haskell function using guards with no case-of?
[英]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
我發現vt
, st
, vf
和sf
的命名更難以閱讀,因為我必須自己跟蹤這些變量的數據流。 保持他們的匿名簡化了理解。
你的#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.