所以,我创建了一个数据类型
data Expr a = Const a
| Expr a :*: Expr a
我为此数据类型
定义Eq
的实例
instance (Eq m) => Eq (Expr m) where
Const a == Const b = a == b
(a :*: b) == (c :*: d) = ((a == c) && (b == d)) || ((a == d) && (b == c))
这个定义意味着在比较两个表达式时顺序无关紧要。但是,当我使用模式匹配来编写一个需要Expr
s的函数时,我不能只写
f (Const 1 :*: a) = ...
但也必须写
f (a :*: Const 1) = ...
为了捕获所有情况,即使我使用(==)
比较两者,它也会返回true。
有没有办法只将上述其中一个写入表达式,让Eq
的实例处理其余部分?模式匹配是否使用或需要Eq
的实例?
答案 0 :(得分:3)
Eq
实例对模式匹配没有任何影响。 ==
只是一个库函数,它检查一个特定的属性,它不一定与实现结构有很大关系,而模式匹配则是在实际的ADT结构中解构一个类型。
也就是说,有可能伪造类似你所问的东西,但我敢说实际做这件事并不是一个好主意 - 不会扩展并可能在以后导致奇怪的问题。
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
matchConstFactor :: Expr a -> Maybe (a, Expr a)
matchConstFactor (Const a :*: b) = Just (a, b)
matchConstFactor (a :*: Const b) = Just (b, a)
matchConstFact _ = Nothing
pattern (:.*:) :: a -> Expr a -> Expr a
pattern a :.*: b <- (matchConstFactor -> Just (a, b))
where a :.*: b = Const a :*: b
答案 1 :(得分:3)
有没有办法只将上面的一个写入表达式,并让(Eq)的实例处理其余的事情?
没有
模式匹配是否使用或需要(Eq)
的实例
仅在匹配(数字,字符或字符串)文字时。您可以在https://www.haskell.org/onlinereport/exps.html#pattern-matching的3.17.2中查看规则,并注意案例7是唯一提及==
的规则。
但您可以使用视图模式:
const1 (Const 1 :*: a) = Just a
const1 (a :*: Const 1) = Just a
const1 _ = Nothing
f (const1 -> Just a) = ...
如果在其他情况下需要其他对称性,这可能太难看了,我现在想不出解决方案。