【问题标题】:Non type-variable argument in the constraint error while using foldl with ++将 foldl 与 ++ 一起使用时,约束错误中的非类型变量参数
【发布时间】:2019-05-20 19:57:59
【问题描述】:

我正在尝试将折叠与 ++ 一起使用。当我检查它的类型时它应该可以工作:

> :t foldl (++)
foldl (++) :: Foldable t => [a] -> t [a] -> [a]

当我尝试这样使用它时

> foldl (++) [1] [1,2,3]

我收到如下错误:

约束中的非类型变量参数:Num [a] (使用 FlexibleContexts 允许这样做)

我做错了什么?

【问题讨论】:

  • 您的折叠计算结果为((([1] ++ 1) ++ 2) ++ 3),这是错误的类型,因为++ 需要两个列表。 GHC 尝试通过要求 Num [a] 将每个 1,2,3 转换为列表来完成这项工作,但失败了。

标签: haskell


【解决方案1】:

我认为你误解了 foldl (++) 函数的类型,t 在这里很重要:

foldl (++) :: <b>Foldable t</b> =&gt; [a] -&gt; <b>t</b> [a] -&gt; [a]

如果您将[1] :: Num n =&gt; [n] 作为第一个参数传递,那不是问题,因为那时您的[1] 类型为[a],因此a ~ n

然而第二个论点一个问题。你在这里传递一个列表[1,2,3] :: Num m =&gt; [m],类型为Num m =&gt; [m],或更规范的Num m =&gt; [] m。让这个匹配t [a]的唯一可能方法是设置t ~ []t是列表type构造函数),然后[a]应该匹配m,但是Haskell 不知道 Num 类型 m 是一个列表 [a],因此它失败了。

你可以用例如:

Prelude> foldl (++) [1] [[2], [3,4]]
[1,2,3,4]

因为这里的 Haskell 会生成一个看起来像这样的表达式:

(([1] ++ [2]) ++ [3]) ++ [4]

相当于:

[1,2,3,4]

我们还可以传递其他Foldable 类型,例如Maybe

Prelude> foldl (++) [1] (Just [2])
[1,2]
Prelude> foldl (++) [1] Nothing
[1]

在这种情况下,第二个参数的类型应该是Maybe [Int]

【讨论】:

  • 所以在这个演员表中 [a] 类似于 [[a]] ?所以这种没有类型类的类型将是 [a] -> [[a]] -> [a] 对吗?
  • @heisenberg7584:确实,因为 [[b]] 的规范形式是 [] ([] b)。那么它指定t ~ [],因此它看到[] b ~ [] a,因此看到b ~ a
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
相关资源
最近更新 更多