我的 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
等人的子表达式。