http://www.iai.uni-bonn.de/~jv/mpc08.pdf - 在本文中,我无法理解以下声明:
instance TreeLike CTree where
...
abs :: CTree a -> Tree a
improve :: (forall m. TreeLike m => m a) -> Tree a
improve m = abs m
有什么区别(forall m.TreeLike m => m a)带来了(我认为TreeLike m => m a就足够了)
为什么它允许abs在这里,如果m in m a可以是任何TreeLike,而不仅仅是CTree?
答案 0 :(得分:9)
这是一种排名2型,而不是存在型。该类型的含义是improve
的参数必须是多态的。您不能将Ctree a
类型的值(例如)传递给improve
。它在类型构造函数中根本不具体。它在类型构造函数中必须是多态的,并且类型构造函数实现Treelike
类的约束。
对于你的第二个问题,这允许improve
的实现选择它想要的m
的任何类型 - 它是实现的选择,并且类型系统对调用者隐藏它。在这种情况下,实施恰好为Ctree
选择m
。那完全没问题。诀窍是improve
的调用者无法在任何地方使用该信息。
这具有实际结果,即不能使用类型的细节构造值 - 它必须使用Treelike
类中的函数来构造它。但是实现可以选择一种特定的类型来使其工作,允许它在内部使用表示的细节。
答案 1 :(得分:4)
m
是否可以是“任何TreeLike”取决于您的观点。
从实施improve
的角度来看,这是真的 - m
可以是任何TreeLike
,因此它会选择一个方便的,并使用abs
。
从论证m
的角度来看 - 也就是说,任何将improve
应用于某些论证的观点,恰恰相反的是:m
实际上必须能任何TreeLike
,而不是我们选择的任何一个(5 :: forall a. Num a => a)
。
将此与数字文字的类型进行比较 - 类似于Num
意味着它是我们想要的任何(forall a. Num a => a)
实例,但是如果函数需要类型Num
的参数它想要的东西可以是选择的任何5
个实例。所以我们可以给它一个多态的Integer
但不是(forall m. TreeLike m => m a) -> Tree a
5。
在很多方面,您可以将多态类型视为函数将类型作为额外参数的含义,它告诉我们要为每个类型变量使用哪种特定类型。因此,要查看forall m. TreeLike m => m a -> Tree a
和(M -> M a) -> Tree a
之间的区别,您可以将其视为M -> M a -> Tree a
与{{1}}之类的内容。