2

让我们定义一个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 x对于该特定情况(和) ,这两个实例似乎都是可匹配的,b ~ Maybe x但编译器不会产生Overlapping Instances错误。

它是如何工作的-XNoOverlappingInstances

而且,顺便说一句,定义这种方法来折叠嵌套是一种安全且可用的方法Maybe吗?

4

1 回答 1

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标志,我认为行为将如你最初预期的那样:重叠实例标志使工作和不工作之间有所不同。

于 2013-09-28T10:49:18.143 回答