4

考虑以下错误代码:

fun x = 
    if (null x) then 0
    else (take 50 x) : (fun (drop 50 x)) 

我注意到,我可以毫无问题地将它加载到 ghci 中,这就是问题所在。
当我尝试评估此功能时,该程序只会检索我一个错误。

关于 if ... then ... else 表达式的默认推理规则,由于两个分支显式检索不同的类型,为什么可以加载(即编译)此代码?我的意思是,为什么编译器无法确定这段代码格式错误?

注意:当然,如果我为此函数添加了正确的类型注释,正如预期的那样,它将被拒绝,但据我所知,如果没有类型注释,它也应该被拒绝。

4

2 回答 2

16

重载的数字文字。Haskell 数字文字是基于类型上下文定义的任何 Num 类的实例。

推断类型解释它:

Prelude> let f x = if null x then 0 else take 50 x : f (drop 50 x)

Prelude> :t f
f :: Num [[a]] => [a] -> [[a]]

这读作“如果你有一个用于 的列表的 Num 类的实例a,那么此函数将 a 的列表带到 a 的列表的列表中。

所以它依赖于一个神话般的 Num 实例来获取列表列表。如果您尝试编译使用它的代码,而不提供列表列表的数字实例,那将是编译错误。

这个例子也说明了为什么先写下类型签名是个好主意。

于 2013-03-02T17:47:29.653 回答
3

让我们检查一下。

Prelude> let fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 
Prelude> :t fun
fun :: Num [[a]] => [a] -> [[a]]

如您所见,编译器Num为您的结果类型推断出一个类。

于 2013-03-02T17:47:19.357 回答