4

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
  1. 有什么区别(forall m. TreeLike m => ma)带来了(我认为 TreeLike m => ma 在这里就足够了)

  2. 为什么它在这里允许 abs,如果 m in ma 可以是任何 TreeLike,而不仅仅是 CTree?

4

2 回答 2

9

那是等级2的类型,而不是存在的类型。该类型的意思是参数improve必须是多态的。您不能将类型的值Ctree a(例如)传递给improve. 它根本不能在类型构造函数中具体化。它在类型构造函数中显式必须是多态的,并具有类型构造函数实现Treelike类的约束。

对于您的第二个问题,这允许实现improve选择m它想要的任何类型 - 这是实现的选择,并且类型系统对调用者隐藏了它。在这种情况下,实现恰好可以选择Ctreem这完全没问题。诀窍是调用者improve无法在任何地方使用该信息。

这样做的实际结果是无法使用类型的详细信息来构造值 - 它必须使用Treelike类中的函数来构造它。但是实现会选择一个特定的类型来工作,允许它在内部使用表示的细节。

于 2012-12-29T00:14:57.003 回答
4

是否m可以是“任何 T​​reeLike”取决于您的观点。

从实现的角度来看improve,是真的——m可以是any TreeLike,所以选择一个方便的,使用abs

从论点的角度来看——m也就是说,任何适用improve于某个论点的观点,恰恰相反的东西成立:m事实上必须能够是any TreeLike,而不是我们选择的单一的。

将此与数字文字的类型进行比较——类似的意思是它是我们想要(5 :: forall a. Num a => a)的任何实例,但如果一个函数需要一个类型的参数,它想要的东西可以是选择的任何实例。所以我们可以给它一个多态的,但不是,比如说,5。Num(forall a. Num a => a)Num5Integer

在许多方面,您可以将多态类型视为函数将类型作为额外参数的意思,它告​​诉它我们希望为每个类型变量使用哪种特定类型。因此,要查看 和 之间的区别(forall m. TreeLike m => m a) -> Tree a,您可以将它们理解为vs.forall m. TreeLike m => m a -> Tree a之类的东西。(M -> M a) -> Tree aM -> M a -> Tree a

于 2012-12-29T00:15:22.540 回答