什么是Skolem?
一个存在量化变量,即它“具有刚性/具体类型,外部世界无法知道,但内部世界可以”。
那么如何使用 Skolems?
TL;博士
unwrapBroken (ExistentiallyTyped x) = x
unwrapOk (ExistentiallyTyped x) = useConstraint x
当 Skolem 有一些您关心的类型类的实例时,它们很有用。您可以(仅?)通过它的约束使用未包装的东西。
简而言之,这里是转义的 skolem (that a
within forall a. ExistentiallyTyped a
):
data ExistentiallyTyped = forall a. SomeConstraint a => ExistentiallyTyped a
unwrapBroken :: forall a. ExistentiallyTyped -> a <---- what? how'd that `a` break out? not the same `a` as in ExistentiallyTyped
unwrapBroken (ExistentiallyTyped x) = x :: a <---- not the same `a` as above!
你不能这样做,a
从包装x :: a
中量化ExistentiallyTyped
,但想想a
就行了unwrapBroken :: forall a. ...
。现在它以某种方式被普遍量化了?!(警告,我认为这开始成为可能的Dependent Types,而 haskell 还没有……)。所以你告诉我这个函数可以返回Int
or String
or AnyFrigginThing
?
不,但你可以x :: a
通过它的约束来利用它:
unwrapOk :: ExistentiallyTyped -> ResultOfUseConstraint
unwrapOk (ExistentiallyTyped x) = useConstraint x
例如,当我想要一个共享某个类型类的类型列表时,我就使用了它:
notPossible :: HasBork a => [Proxy a]
notPossible = [Proxy @Thing1, Proxy @Thing2]
-- Error! expected a `Proxy a` but got a `Proxy Thing1`
所以与其:
data Borkable = forall a. HasBork a => Borkable a
borks :: [Borkable]
borks = [thing1, thing2]
later = useBork <$> borks