只有多态函数可以应用于存在类型的值。 这些属性可以用表达式的相应量词来表示,并以自然变换为特征。
类似地,当我们定义一个类型构造函数
时data List a = Nil | Cons a (List a)
此类型构造函数适用于所有a
,而类型族允许使用非统一类型构造函数
type family TRes i o
type instance TRes Bool = String
type instance TRes String = Bool
正是这种自然转变的特征正是这种“均匀性”的理念。在类型级别?
是否存在与Rank-n类型的价值水平相当的强迫自然性?
ApplyNat :: (forall a. a -> F a) -> b -> F b
答案 0 :(得分:2)
我认为你在这里混淆了几个不同的想法。
此类型构造函数适用于所有
a
。
总计。 List :: * -> *
会根据*
类型的任何参数a
生成有效类型*
。 Haskell 98数据类型总是总数,但正如您所指出的,在现代Haskell中,您可以编写不涵盖所有可能情况的类型系列。 TRes Int
不是真实的"类型,在它不包含任何值的意义上,它不会减少到任何其他类型,并且它不等于TRes Int
以外的任何类型。
Haskell在值级别或类型级别没有整体检查器(除了关于不可判定的实例的规则,这是一个钝器),因此,就像没有办法排除undefined
值一样,没有办法排除"卡住"输入TRes Int
之类的系列。 (有关"卡住"类型系列的详细信息,请参阅TypeInType
设计师Richard Eisenberg的this blog post。)
自然是一个完全不同的想法。在值级Haskell中,f
和g
之间的自然转换是将类型f x
的值映射到类型g x
的值的多态函数,而不知道x
的任何内容。 1}}。
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
的类型。
在现实世界中,你会使用什么类型级别的自然转换?我不知道。你可能不会。