【问题标题】:Understanding Haskell RankNTypes Error message了解 Haskell RankNTypes 错误消息
【发布时间】:2019-05-09 17:52:07
【问题描述】:

我正在尝试了解 RankNTypes。

为什么编译器在这种情况下会抱怨a 不是[a]

> :{
> | tupleF2 :: (forall a . a -> b) -> (a1, a2) -> (b, b)
> | tupleF2 elemF2 (x, y) = (elemF2 x, elemF2 y)
> | :}

> :t tupleF2  tupleF2 :: (forall a. a -> b) -> (a1, a2) -> (b, b)

> :t tupleF2 length

<interactive>:1:9: error:
    • Couldn't match type ‘a’ with ‘[a0]’
      ‘a’ is a rigid type variable bound by
        a type expected by the context:
          forall a. a -> Int
        at <interactive>:1:1-14
      Expected type: a -> Int
        Actual type: [a0] -> Int
    • In the first argument of ‘tupleF2’, namely ‘length’
      In the expression: tupleF2 length

虽然以下类型检查正常?并且t 可以使用t a

> :t tupleF length
tupleF length :: Foldable t => (t a, t a) -> (Int, Int)
:t tupleF
tupleF :: (t -> b) -> (t, t) -> (b, b)

上述编译失败是否仅在启用RankNTypes 时发生。任何了解正在发生的事情的指针都会很棒。

谢谢。

【问题讨论】:

  • 我不确定您的第二个示例中的 tupleF 是什么,但在第一个示例中,错误的原因似乎很清楚。 tupleF2 需要 forall a . a -&gt; b 类型的输入 - 即一个可以接受 any 输入并产生固定类型 b 的输出的函数。我不确定是否存在任何这样的功能,除了const x,其中x :: b - 但length 显然不是一个。例如,您不能将length 应用于Int
  • 无论tupleF 是什么,它的参数类型中都没有forall,所以它可以接受任何函数。

标签: haskell typechecking rank-n-types


【解决方案1】:

forall a . a -&gt; b 是函数f 的类型,它可以将任何类型的值a 转换为某个类型的值b。请注意,f 必须准备好接受任何内容作为输入,即所有这些都必须输入检查

f ()
f 32
f True
f 'a'
f "hello"
f (True, [2], False)

length 不满足要求,例如length () 输入错误——length 想要一个可折叠(如列表)作为输入,而 () 不行。

因此,tupleF2 length 输入错误。

务实的,注意f只能是一个常量函数,比如

f x = True  -- assuming b = Bool

确实,参数化 保证只有常量函数可以具有forall a . a -&gt; b 类型。可以尝试tupleF2 (const True) ((),"hello")获取(True, True)

【讨论】:

  • 谢谢,这在我输入评论时出现,实际上是相同的。我对更高等级的类型没有足够的信心来回答它,但我很高兴我基本上是正确的。
猜你喜欢
  • 2016-01-31
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多