【发布时间】:2014-10-08 07:48:11
【问题描述】:
我的 Haskell 项目包括一个表达式求值器,就本题而言,它可以简化为:
data Expression a where
I :: Int -> Expression Int
B :: Bool -> Expression Bool
Add :: Expression Int -> Expression Int -> Expression Int
Mul :: Expression Int -> Expression Int -> Expression Int
Eq :: Expression Int -> Expression Int -> Expression Bool
And :: Expression Bool -> Expression Bool -> Expression Bool
Or :: Expression Bool -> Expression Bool -> Expression Bool
If :: Expression Bool -> Expression a -> Expression a -> Expression a
-- Reduces an Expression down to the simplest representation.
reduce :: Expression a -> Expression a
-- ... implementation ...
实现这一点的直接方法是编写一个case 表达式来递归评估和模式匹配,如下所示:
reduce (Add x y) = case (reduce x, reduce y) of
(I x', I y') -> I $ x' + y'
(x', y') -> Add x' y'
reduce (Mul x y) = case (reduce x, reduce y) of
(I x', I y') -> I $ x' * y'
(x', y') -> Mul x' y'
reduce (And x y) = case (reduce x, reduce y) of
(B x', B y') -> B $ x' && y'
(x', y') -> And x' y'
-- ... and similarly for other cases.
对我来说,这个定义看起来有些尴尬,所以我使用模式保护重写了定义,如下所示:
reduce (Add x y) | I x' <- reduce x
, I y' <- reduce y
= I $ x' + y'
我认为与case 表达式相比,这个定义看起来更清晰,但是当为不同的构造函数定义多个模式时,该模式会重复多次。
reduce (Add x y) | I x' <- reduce x
, I y' <- reduce y
= I $ x' + y'
reduce (Mul x y) | I x' <- reduce x
, I y' <- reduce y
= I $ x' * y'
注意到这些重复的模式,我希望有一些语法或结构可以减少模式匹配中的重复。是否有一种普遍接受的方法来简化这些定义?
编辑:在查看了模式防护之后,我意识到它们在这里不能作为替代品。尽管当 x 和 y 可以减少到 I _ 时它们提供相同的结果,但是当模式保护不匹配时它们不会减少任何值。我仍然希望reduce 简化Add 等的子表达式。
【问题讨论】:
标签: haskell pattern-matching pattern-guards