【问题标题】:Haskell function composition - wrongly inferred typeHaskell 函数组合 - 错误推断的类型
【发布时间】:2013-05-10 09:13:32
【问题描述】:

在下面的 Haskell 代码中,函数 typeError 不进行类型检查。

wrap x = [x]

listf :: [[a]] -> [[a]]
listf = id

typeCheck :: [a] -> [[a]]
typeCheck x = listf (wrap x)

typeError :: [a] -> [[a]]
typeError = wrap . listf

如果未注释,GHC 会产生此错误:

Couldn't match type `a' with `[a0]'
  `a' is a rigid type variable bound by
      the type signature for typeError :: [a] -> [[a]] at tim.hs:10:1
Expected type: [a] -> [a]
  Actual type: [[a0]] -> [[a0]]
In the second argument of `(.)', namely `listf'
In the expression: wrap . listf

我不明白为什么。 a 应该能够与 [a0] 统一 - 它们是独立的类型变量。这正是它为 typeCheck 推断的类型 - 但在使用 . 运算符时不是。

Hugs 会产生一个非常相似且同样虚假的错误消息:

ERROR "repro.hs":10 - Inferred type is not general enough
*** Expression    : typeError
*** Expected type : [a] -> [[a]]
*** Inferred type : [[a]] -> [[[a]]]

此外,这很好用:

listf' :: [a] -> [a]
listf' = id

typeCheck' :: [a] -> [[a]]
typeCheck' = wrap . listf'

该问题仅发生在 [[a]] 或 [[[a]]] 或更大的情况下。这里有什么关系?

【问题讨论】:

    标签: haskell functional-programming dot-operator


    【解决方案1】:

    你好像把这里的函数组合倒过来了。

    -- This
    typeCheck :: [a] -> [[a]]
    typeCheck x = listf (wrap x)
    
    -- is the same as
    typeCheck' :: [a] -> [[a]]
    typeCheck' = listf . wrap
    
    -- while this
    typeError :: [a] -> [[a]]
    typeError = wrap . listf
    
    -- is the same as
    typeError' :: [a] -> [[a]] 
    typeError' x = wrap (listf x)
    

    现在应该很明显为什么这不起作用。 listf 要求它的参数是[[a]],但typeError 的签名声称它适用于任何[a]

    【讨论】:

    • 该死,这就是我在多年未使用 Haskell 后尝试修复此代码中的错误的结果。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 2011-03-08
    相关资源
    最近更新 更多