Haskell RankNTypes笔记

这个蛋疼的扩展的存在的必要性在于, 虽然Haskell默认泛型, 但是一个类型参数默认在一个特化的函数类型中也只能有一个特化

例如


length :: [a] -> Int

lengthInt = length :: [Int] -> Int

lengthChar = length :: String -> Int

当length这个函数作用于[Int]上时, 实际上length被特化成了lengthInt; 同理, length在String上会被特化为lengthChar

这个搞法通常是没有问题, 但是有时我们会发现需要两个特化

例如这个到处都是的例子


foo :: ([x] -> Int) -> ([a], [b]) -> (Int, Int)

foo f (a, b) = (f a, f b)

这看起来很美好, 但你们这样是不行的, 我建议你们再去学习一个

原因可能已经猜到了, 就是x这个类型参数不知道要被特化成a还是b

例如foo length [1] “a”里面, x应该是Int还是Char?

由于这个Haskell的设计失误(?), 我们需要RankNTypes, 并把foo的类型签名改成


foo :: (forall x. [x] -> Int) -> ([a], [b]) -> (Int, Int)

注意不要把这里的forall和其它的搞混啦, 可以参考这个SO问题

对了ST防止逃逸的办法也是相当有趣的, 感兴趣可以看看这个

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s