为什么这些实例不会产生重叠实例错误

时间:2013-09-28 10:28:14

标签: haskell

让我们定义一个collapse函数,将任何可能嵌套的Maybe (Maybe (... a)...)折叠为Maybe a

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoOverlappingInstances #-}
{-# LANGUAGE TypeFamilies #-}

module MaybeCollapsable where

class M a b where
  collapse :: Maybe a -> Maybe b

instance (a ~ b) => M a b where
  collapse = id

instance M a b => M (Maybe a) b where
  collapse Nothing = Nothing
  collapse (Just a) = collapse a

效果很好

> collapse (Just (Just (Just 1)))
Just 1

虽然,很奇怪。这两个实例似乎都可以匹配特定情况(a ~ Maybe xb ~ Maybe x),但编译器不会产生Overlapping Instances错误。

如何使用-XNoOverlappingInstances

顺便说一下,定义这种折叠嵌套Maybe的方法是一种安全可行的方法吗?

1 个答案:

答案 0 :(得分:6)

我认为问题可能是IncoherentInstances覆盖了NoOverlappingInstances指令。如果删除IncoherentInstances,则代码会出现重叠实例错误。 GHC手册对此并不清楚(http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/type-class-extensions.html#instance-overlap),但这两个标志明确相关。

如果您关闭IncoherentInstances并启用OverlappingInstances,则代码可以正常运行。所以删除IncoherentInstances标志,我认为行为将如您最初预期的那样:重叠实例标志使工作与不工作之间存在差异。