困扰Haskell"存在包装"

时间:2017-05-01 01:56:37

标签: haskell

来自Haskell文件:

import GHC.Exts (Constraint)

-- |Existential wrapper 
data Some :: (* -> Constraint) -> * where
  Some :: f a => { unSome :: a } -> Some f

我知道Constraint表示与*不同的一种,可用于对=>左侧显示的上下文类型进行分类。

但在什么意义上Some是一个存在主义的包装?怎么可以这样使用呢?

1 个答案:

答案 0 :(得分:3)

奇怪的GADT /记录语法看起来不应该被编译出去,我们可以通过设置f ~ Eq来了解这里发生了什么:

Some :: Eq a => a -> Some Eq

所以,给定一个Eq可用的东西,我们得到Some Eq可用的东西。我们将此应用于'a' :: Char,看看会发生什么:

(Some :: Eq Char => Char -> Some Eq) ('a' :: Char) :: Some Eq

正如你所看到的,我们已经忘记了#34;这个值的确切类型,但是记得"它是Eq可以使用的。

您提供的GADT只是从Eq到类似* -> Constraint的任何内容的概括:

(Eq :: * -> Constraint) (Char :: *) :: Constraint
(f :: * -> Constraint) (a :: *) :: Constraint

为什么它被称为"存在",GADT在构造函数声明中隐藏了一个隐含的forall

Some :: forall a. f a => { unSome :: a } -> Some f

Some f上进行模式匹配后,您会获得f a => a类型的值,其中a由于技术原因无法逃避其范围。 (这称为skolem)您可以使用这样的CPS组合器来处理它:

ambiguously :: (forall s. f s => s -> r) -> Some f -> r
ambiguously f (Some s) = f s

现在你有ambiguously show :: Some Show -> String,它显示了Some Show能够做到的事情。它被称为"含糊不清"因为它使用的实际类型不明确(即它适用于ambiguously show $ Some 'a'ambiguously show $ Some "asdf"

我们无法做到

disambiguate :: f a => Some f -> a
disambiguate (Some a) = a

因为上述限制。

My (unpublished) library与此相关,更为一般。