Rigid / skolem 类型变量:可以作为参数但使用局部 where/let 语句转义范围
Rigid / skolem type variable: fine as parameter but escaping scope with local where/let statement
根据 What are skolems?,这有效:
{-# LANGUAGE ExistentialQuantification #-}
data AnyEq = forall a. Eq a => AE a
reflexive :: AnyEq -> Bool
reflexive (AE x) = x == x
但为什么不是这样:
reflexive2 :: AnyEq -> Bool
reflexive2 ae = x == x
where
AE x = ae
(或 let
的类似版本)。它产生的错误包括:
Couldn't match expected type ‘p’ with actual type ‘a’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor: AE :: forall a. Eq a => a -> AnyEq,
in a pattern binding
at Skolem.hs:74:4-7
是否可以通过添加一些类型声明使其工作(有点像该问题中 withContext
示例的 s :: forall a. I a -> String
解决方案)。我觉得我想在某处添加一个Eq x
。
我(可能天真)对 reflexive
工作原理的理解如下:
- 它采用
AnyEq
类型的值。只要它是 Eq
的实例,它就会在其中嵌入任何类型的值。此内部类型在 reflexive
的类型签名中不明显,并且在编译 reflexive
时未知。
- 绑定
(AE x) = ae
使 x
成为该未知类型的值,但已知是 Eq
的实例。 (所以就像 myEq :: Eq a => a -> a -> Bool; myEq x y = x == y
中的变量 x 和 y)
==
运算符很高兴基于隐含的 class 约束。
我不明白为什么 reflexive2
不这样做,除了“单态限制”或“单态本地绑定”之类的东西,这有时会让事情变得很奇怪。我尝试使用 NoMonomorphismRestriction
和 NoMonoLocalBinds
的所有组合进行编译,但无济于事。
谢谢。
所以我想我找到了答案 in the documentation(所有地方!)。这说明:
- 您不能在 let 或 where 绑定组中的存在量化构造函数上进行模式匹配
- 这个限制的原因确实是一个实现
- 我们会看到它有多烦人
还有一个request to lift the restriction(虽然看起来有点难度)
就我个人而言,现在我想我明白了,这并不那么烦人。但我确实认为生成的错误消息具有误导性(因为我不认为问题是范围泄漏),所以会要求更改它。 (如果生成的错误消息有对文档的引用,那也很好,所以也会通过询问来推动我的运气。)
感谢大家的评论,如果您认为我的观点有误,请告诉我。大卫.
根据 What are skolems?,这有效:
{-# LANGUAGE ExistentialQuantification #-}
data AnyEq = forall a. Eq a => AE a
reflexive :: AnyEq -> Bool
reflexive (AE x) = x == x
但为什么不是这样:
reflexive2 :: AnyEq -> Bool
reflexive2 ae = x == x
where
AE x = ae
(或 let
的类似版本)。它产生的错误包括:
Couldn't match expected type ‘p’ with actual type ‘a’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor: AE :: forall a. Eq a => a -> AnyEq,
in a pattern binding
at Skolem.hs:74:4-7
是否可以通过添加一些类型声明使其工作(有点像该问题中 withContext
示例的 s :: forall a. I a -> String
解决方案)。我觉得我想在某处添加一个Eq x
。
我(可能天真)对 reflexive
工作原理的理解如下:
- 它采用
AnyEq
类型的值。只要它是Eq
的实例,它就会在其中嵌入任何类型的值。此内部类型在reflexive
的类型签名中不明显,并且在编译reflexive
时未知。 - 绑定
(AE x) = ae
使x
成为该未知类型的值,但已知是Eq
的实例。 (所以就像myEq :: Eq a => a -> a -> Bool; myEq x y = x == y
中的变量 x 和 y) ==
运算符很高兴基于隐含的 class 约束。
我不明白为什么 reflexive2
不这样做,除了“单态限制”或“单态本地绑定”之类的东西,这有时会让事情变得很奇怪。我尝试使用 NoMonomorphismRestriction
和 NoMonoLocalBinds
的所有组合进行编译,但无济于事。
谢谢。
所以我想我找到了答案 in the documentation(所有地方!)。这说明:
- 您不能在 let 或 where 绑定组中的存在量化构造函数上进行模式匹配
- 这个限制的原因确实是一个实现
- 我们会看到它有多烦人
还有一个request to lift the restriction(虽然看起来有点难度)
就我个人而言,现在我想我明白了,这并不那么烦人。但我确实认为生成的错误消息具有误导性(因为我不认为问题是范围泄漏),所以会要求更改它。 (如果生成的错误消息有对文档的引用,那也很好,所以也会通过询问来推动我的运气。)
感谢大家的评论,如果您认为我的观点有误,请告诉我。大卫.