方程的替代实例的模式匹配

时间:2017-06-04 19:35:58

标签: haskell pattern-matching equality typeclass

所以,我创建了一个数据类型

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的实例?

2 个答案:

答案 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) = ...

如果在其他情况下需要其他对称性,这可能太难看了,我现在想不出解决方案。