“约束中的非类型变量参数”的真正含义是什么?

时间:2020-03-15 16:20:56

标签: haskell type-deduction

例如:

map (+1) 2

ghci产量

<interactive>:23:1: error:
* Non type-variable argument in the constraint: Num [b]
  (Use FlexibleContexts to permit this)
* When checking the inferred type
    it :: forall b. (Num b, Num [b]) => [b]

我已经看到许多与我的问题类似的问题,但是所有问题似乎都只能回答我们可以得出的结论(map的第二个参数的类型是错误的)以及如何解决它-但是实际上不是什么错误意味着。到底哪里出问题了?

2 个答案:

答案 0 :(得分:3)

在语句的类型推导过程中出现错误。

因为

  1. (+1)的类型为Num a => a -> a
  2. 2的类型为Num a => a
  3. map的类型为(a -> b) -> [a] -> [b]

我们知道map (+1)的类型必须为(Num b) => [b] -> [b],因此map (+1) 2的类型必须为(Num b, Num [b]) => [b]。但是[b]不仅是类型变量,它是某种类型变量的 List ,其中list是数据构造函数。在Haskell的替代版本中,其中不存在列表的语法糖,我们可以编写(Num b, Num (List b))

这是一个问题,因为默认情况下,Haskell不支持约束的非类型变量参数。因此,问题的确切本质不是Haskell不知道如何映射数字-而是它不允许我们的函数调用产生的类型的值。

但并非必须遵循该规则。通过在调用ghci时添加-XFlexibleContexts,现在允许我们的方法产生的排序类型。原因是Haskell中的文字2并不真正代表数字-它代表Num a => a类型的对象,该对象是使用{{1 }}。因此,语句2等效于fromIntegral。这意味着,只要有适当的实例化,文字“ 2”就可以代表任何内容-包括列表。

答案 1 :(得分:2)

2的类型为Num a => a;除了必须具有a实例以外,我们没有指定Num 是什么

map (+1)的类型为Num b => [b] -> [b];我们已经指定了b是什么,除了它必须有一个Num实例。

确定map (+1) 2的类型时,基本上就是在统一Num a ~ Num b => [b]

2 ::                  Num a    => a
map (+1) ::    Num b           => [b] -> [b]
map (+1) 2 :: (Num b, Num [b]) =>        [b]

这就是问题所在。 Num要求使用像ab这样的类型变量,而不是像[b]这样的多态类型作为参数。

相关问题