每什么是 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
是否可以通过添加一些类型声明来使其工作(有点像该问题s :: forall a. I a -> String
中示例的解决方案withContext
)。我觉得我想在Eq x
某个地方添加一个。
我(可能是幼稚的)对reflexive
工作原理的理解如下:
- 它需要一个 type 的值
AnyEq
。这在其中嵌入了任何类型的值,只要它是Eq
. 这种内部类型在的类型签名中并不明显,并且在编译reflexive
时是未知的。reflexive
- 该绑定生成
(AE x) = ae
了x
一个未知类型的值,但已知它是Eq
. (所以就像变量 x 和 y 一样myEq :: Eq a => a -> a -> Bool; myEq x y = x == y
) ==
基于隐含的类约束,操作员很高兴。
我想不出为什么reflexive2
不做同样的事情,除了像“单态限制”或“单局部绑定”这样的事情,有时会让事情变得很奇怪。我尝试使用 and 的所有组合进行编译NoMonomorphismRestriction
,NoMonoLocalBinds
但无济于事。
谢谢。