用普遍量化的约束重写规则/特化类型错误

时间:2016-07-04 14:12:29

标签: haskell ghc typeclass lens

我正在尝试实现一些特定于类型的特化 一些与Prism一起工作的函数,我遇到了困难 GHC 8.(我遇到GHC <8的不同问题,但那是 另一个问题)。

问题的一个(设计的)最小例子:

foo :: Prism' s a -> Prism' s a
foo = id

{-# RULES "foo/foo'" foo = foo' #-}
foo' :: Prism' Char Bool -> Prism' Char Bool
foo' = id

这会导致编译错误:

error:
• Couldn't match type ‘p0 Bool (f0 Bool) -> p0 Char (f0 Char)’
                 with ‘forall (p :: * -> * -> *) (f :: * -> *).
                       (Choice p, Applicative f) =>
                       p Bool (f Bool) -> p Char (f Char)’
  Expected type: Prism' Char Bool
    Actual type: p0 Bool (f0 Bool) -> p0 Char (f0 Char)
• In the expression: foo'
  When checking the transformation rule "foo/foo'"

它看起来像重写规则类型检查的一面 “忘记”它的背景。这里到底发生了什么,以及如何发生 我可以让GHC开心吗?

2 个答案:

答案 0 :(得分:4)

这实际上是一个老问题,即排名N类型没有形成哪种类型更多且哪种类型更不通用的适当层次结构。看起来这个特定情况可能可以解析,但是肯定不可能为一般的秩-N函数编写重写规则。

幸运的是,这对镜头和朋友来说不是什么大问题,因为这些都是单形版本!

foo₀ :: APrism' s a -> APrism' s a
foo₀ = id

{-# RULES "foo/foo'" foo₀ = foo' #-}
foo' :: APrism' Char Bool -> APrism' Char Bool
foo' = id

foo :: Prism' s a -> Prism' s a
foo p = clonePrism $ foo₀ (clonePrism p)

答案 1 :(得分:0)

似乎GHC以某种方式感到困惑。 GHC通常假设将所有forall和类上下文尽可能地向左浮动,但似乎在这里没有恰当的时间发生。推测:这可能与尝试支持当前损坏的ImpredicativeTypes扩展有关。但是,我们可以手动完成,此时GHC停止抱怨该规则。

Dan Doel告诉我,接受id作为这些函数的实现本身就是GHC 7.10中的编译器错误,所以我会把它们写出来。

foo :: (Choice p, Applicative f) => Prism' s a -> p a (f a) -> p s (f s)
foo x = x

-- Avoid a warning about the rule not firing.
{-# INLINE [0] foo #-}

foo' :: (Choice p, Applicative f) => Prism' Char Bool -> p Bool (f Bool) -> p Char (f Char)
foo' x = x

{-# RULES "foo/foo'" foo = foo' #-}