具有普遍量化约束的重写规则/专业化类型错误
Rewrite rule / specialisation type error with universally quantified constraints
我正在尝试实现一些特定于类型的专业化
一些适用于 Prisms 的功能,我在使用时遇到了困难
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'"
在我看来,它像是重写规则类型检查的一方面
"forgets" 它的上下文。这里究竟发生了什么,以及如何
我能让 GHC 开心吗?
这本质上是一个老问题,即 rank-N 类型没有建立适当的层次结构来区分哪种类型更普遍,哪种类型更不普遍。似乎这种特定情况 可以 解决,但肯定不可能为一般的 rank-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)
GHC 似乎不知何故变得混乱了。 GHC 通常 应该 将所有 forall
和 class 上下文尽可能地向左浮动,但似乎并没有在正确的时间发生。推测:这可能与支持当前损坏的 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' #-}
我正在尝试实现一些特定于类型的专业化 一些适用于 Prisms 的功能,我在使用时遇到了困难 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'"
在我看来,它像是重写规则类型检查的一方面 "forgets" 它的上下文。这里究竟发生了什么,以及如何 我能让 GHC 开心吗?
这本质上是一个老问题,即 rank-N 类型没有建立适当的层次结构来区分哪种类型更普遍,哪种类型更不普遍。似乎这种特定情况 可以 解决,但肯定不可能为一般的 rank-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)
GHC 似乎不知何故变得混乱了。 GHC 通常 应该 将所有 forall
和 class 上下文尽可能地向左浮动,但似乎并没有在正确的时间发生。推测:这可能与支持当前损坏的 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' #-}