类型构造函数和存在类型

Types constructors and existential types

只有多态函数可以应用于存在类型的值。 这些性质可以用表达式对应的量词来表示,并用自然变换来表征。

同样,当我们定义一个类型构造函数时

data List a = Nil | Cons a (List a)

此类型构造函数适用于所有 a 而类型族允许具有非统一类型构造函数

type family TRes i o
type instance TRes Bool = String
type instance TRes String  = Bool

哪种自然转换恰恰在类型级别表征了 "uniformity" 的这种想法?

是否有像我们在 rank-n 类型的值级别上那样的强制自然性的等价物?

ApplyNat :: (forall a. a -> F a) -> b -> F b

我认为您在这里混淆了几个不同的想法。

This type constructor works for all a.

那是总数List :: * -> * 给定类型 * 的任何参数 a 生成类型 * 的有效类型。 Haskell 98 种数据类型总是总数,但是,正如您所指出的,在现代 Haskell 中,您可以编写不涵盖所有可能情况的类型族。 TRes Int 不是 "real" 类型,因为它不包含任何值,它不会减少到任何其他类型,并且不等于 TRes Int 以外的任何类型。

Haskell 在值级别或类型级别没有完整性检查器(除了关于不可判定实例的规则,这是一种钝器),所以,就像没有办法排除 undefined 值,无法排除像 TRes Int 这样的 "stuck" 类型族。 (有关 "stuck" 类型族的更多信息,请参阅 TypeInType 的设计者 Richard Eisenberg 的 this blog post。)

自然是一个完全不同的想法。在值级别 Haskell 中,fg 之间的自然转换是一个多态函数,将类型 f x 的值映射到类型 g x 的值,而不知道关于 x.

的任何事情
type f ~> g = forall x. f x -> g x

在 GHC 8 和 TypeInType 中,我们可以使用与谈论类型相同的语言来谈论种类,因为种类 类型。类型表达式 forall x. f x -> g x 的种类为 * ((~>) :: forall k. (k -> *) -> (k -> *) -> *),因此它也是一个完全有效的类型分类器。具有该种类的类型是一个多态类型函数,将种类 f x 的类型映射到种类 g x.

的类型

在现实世界中,您会使用类型级别的自然转换做什么?我不知道。你可能不会。