[英]Haskell - Why are we using RankNTypes for single type outputs?
[英]Type checking with RankNTypes in Haskell
我试图了解Haskell中的RankNTypes
并找到了这个例子:
check :: Eq b => (forall a. [a] -> b) -> [c] -> [d] -> Bool
check f l1 l2 = f l1 == f l2
(如果我的理解是正确的,这相当于check :: forall bc d. Eq b => (forall a. [a] -> b) -> [c] -> [d] -> Bool
。)
好的,到目前为止一切顺利。 现在,如果删除了明确的forall a
,GHC会产生以下错误:
Could not deduce (c ~ a)
from the context (Eq b)
[…]
Could not deduce (d ~ a)
from the context (Eq b)
[…]
删除嵌套的forall
,类型签名变为
check :: forall a b c d. Eq b => ([a] -> b) -> [c] -> [d] -> Bool
很容易l1
为什么这会导致类型检查失败,因为l1
和l2
应该有类型[a]
让我们将它们传递给f
,但是为什么在指定f
的类型时不是这种情况(forall a. [a] ->b)
? 事实上a
只是在parens内部完全答案吗? 即类型检查器将接受
[c] -> b ~ (forall a. [a] -> b)
[d] -> b ~ (forall a. [a] -> b)
(编辑:修复。谢谢,博伊德!)
因为类型的函数(forall a. a -> b)
可以列出任何列表吗?
当f = \\xs -> ...
用明确的Rank2量化写入时forall a. [a] -> b
forall a. [a] -> b
您可以将其视为新功能
f = Λa -> \xs -> ...
其中Λ
是一个特殊的拉姆达,需要一个类型参数 ,以确定哪个特定类型a
它会在函数体使用。 每次调用函数时都会应用此类型参数,就像在每次调用时应用正常的lambda绑定一样。 这就是GHC内部处理forall
。
在明确forall
“d版本, f
可以每次被调用所以时间施加到不同类型的参数a
可以在每次将其解析为不同的类型,一旦c
并一次d
。
在没有内部版本forall
,对于这种类型的应用程序a
只发生一次,当check
被调用。 所以每次调用f
都必须使用相同的a
。 当然,这会失败,因为在不同类型的列表上调用f
。
很容易理解为什么这会导致类型检查失败,因为l1和l2应该有类型[a]让我们将它们传递给f,但是为什么在指定f的类型时不是这种情况(forall a。[a] - > b)?
因为类型(forall a. [a] -> B)
可以与[C] -> B
和(单独) [D] -> B
统一。 但是,类型[A] -> B
不能与[C] -> B
或[D] -> B
统一。
事实上a只是在parens内部完全答案吗?
基本上。 当你在forall范围内时,你必须为每个类型变量选择一个特定的类型,但在外面你可以多次使用forall并且每次都选择不同的特定类型。
即类型检查器将接受
[c] ~ (forall a. a -> b) [d] ~ (forall a. a -> b)
因为类型的函数(forall a。a - > b)可以列出任何列表吗?
小心。 你似乎在那里失去了一些“[]”字符。 此外,你并没有完全正确的统一。 类型检查器将同时接受:
[C] -> B ~ (forall a. [a] -> B)
[D] -> B ~ (forall a. [a] -> B)
它也不会接受:
[C] -> B ~ [A] -> B
[D] -> B ~ [A] -> B
您可以在逆变场中重写通用量化,并在协变场中进行存在量化(在Haskell中不合法,但原则上)。
check' :: exists c' d'. forall b c d. Eq b
=> ([c'] -> b) -> ([d'] -> b) -> [c] -> [d] -> Bool
很明显这是有效的:对于c ~ C
, d ~ D
选择c' ~ C
和d' ~ D
,那么函数就是简单
check'' :: forall b . Eq b => ([C] -> b) -> ([D] -> b) -> [C] -> [D] -> Bool
不确定这是否能回答你的问题,但这是查看排名2类型的一种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.