Haskell和Rank-N多态性

dco*_*set 5 haskell types

以下假设的Haskell代码有什么错误?当我在脑中编译它时,它应该输出"1".

foo :: forall a. forall b. forall c. (a -> b) -> c -> Integer -> b
foo f x n = if n > 0 then f True else f x

bar :: forall a. a -> Integer
bar x = 1

main = do
     putStrLn (show (foo bar 1 2))
Run Code Online (Sandbox Code Playgroud)

GHC抱怨:

$ ghc -XRankNTypes -XScopedTypeVariables poly.hs 

poly.hs:2:28:
     Couldn't match expected type `a' against inferred type `Bool'
       `a' is a rigid type variable bound by
           the type signature for `foo' at poly.hs:1:14
     In the first argument of `f', namely `True'
     In the expression: f True
     In the expression: if n > 0 then f True else f x

poly.hs:2:40:
     Couldn't match expected type `Bool' against inferred type `c'
       `c' is a rigid type variable bound by
            the type signature for `foo' at poly.hs:1:34
     In the first argument of `f', namely `x'
     In the expression: f x
     In the expression: if n > 0 then f True else f x
Run Code Online (Sandbox Code Playgroud)

那是什么意思?是不是有效的Rank-N多态性?(免责声明:我绝对不是Haskell程序员,但OCaml不支持这种显式类型签名.)

sep*_*p2k 17

您实际上并没在代码中使用rank-N多态性.

foo :: forall a. forall b. forall c. (a -> b) -> c -> Integer -> b
Run Code Online (Sandbox Code Playgroud)

这是普通的排名-1类型.它读取:forall a,b和c这个函数可以采用类型的函数,类型a -> b的值c和a Integer并返回类型的值b.所以它说它可以采用类型Bool -> Integer函数或类型函数Integer -> Integer.它并没有说该函数必须在其参数中具有多态性.要说,你需要使用:

foo :: forall b. forall c. (forall a. a -> b) -> c -> Integer -> b
Run Code Online (Sandbox Code Playgroud)

现在你要说函数的类型需要在forall a. a -> b哪里b修复,但是a是新引入的变量,所以函数需要在其参数中具有多态性.

  • 是否有任何有趣的类型forall a居住者.a - > b?想到的唯一一个是一个函数,它接受一个参数但根本不使用它:例如fx = 12,就像他上面的函数栏一样. (3认同)
  • 我猜S和K在Haskell的实现中非常重要,所以我可能不应该侮辱const,即使它看起来很无聊...... (2认同)