从forall量化中扣除等级

时间:2014-04-07 17:59:08

标签: haskell

鉴于以下代码(来自Yoneda Lemma explanation):

{-# LANGUAGE RankNTypes #-}

check1 :: a -> (forall b . (a -> b) -> b)
check1 a f = f a

uncheck1 :: (forall b . (a -> b) -> b) -> a
uncheck1 t = t id
forall中确认check1 rank-1的{​​{1}}量化似乎是ghci

$ :t check1
check1 :: a -> (a -> b) -> b
$ :t uncheck1
uncheck1 :: (forall b. (a -> b) -> b) -> a

我无法弄清楚为什么check1具有rank-1类型签名,而uncheck1仍保留rank-2类型签名。我将check1的类型签名读作"对于所有类型b,请接受a类型的函数到b,其中a是固定的,并返回类型b"的值。这使我相信不允许用户提前选择类型b(与类型a不同),因此类型应为rank-2。在尝试了解明确的forall签名是否应该被读为1级或更高级别时,我肯定会发现一些细微差别。

更新 虽然我已经接受了下面的答案,但capital lambda来自Lennart Augustsson的this email explanationforall方面非常明确和直观 - 它切断了来电者的混淆,并清楚地显示了如何进行打字 - 级别lambda来解释{{1}}。

1 个答案:

答案 0 :(得分:5)

碰巧我们可以漂浮在forall check1,因为它位于该箭头的右侧。

 check1 :: a -> (forall b. (a -> b) -> b)
 check1 :: forall b. a -> (a -> b) -> b

uncheck1的直觉,谁能选择b是什么?某些不是来电者,因为该功能必须适用于所有b

check1中,调用者确实可以选择b,因为我们必须返回一个适用于所有b的函数。我们将功能返回给他们,因此他们可以将它专门用于他们选择的任何内容。由于调用者无论如何都可以选择,这与

完全相同
check1 :: a -> (a -> b) -> b

HaskellWiki页面对此进行了讨论。