推断if ...然后......其他奇怪的行为

时间:2013-03-02 17:42:58

标签: haskell if-statement type-inference

考虑以下不良代码:

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

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

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

注意:当然,如果我为此函数添加正确的类型注释,正如预期的那样它将被拒绝,但在我的理解中,它也应该在没有类型注释的情况下被拒绝。

2 个答案:

答案 0 :(得分:16)

重载numeric literals。 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]]

如果你有a列表列表的Num类实例,则读取为"然后该函数将a列表列为a列表。

所以它依赖于Num的神话实例列表列表。如果您尝试编译使用此代码的代码,而不为列表列表提供数字实例,则会出现编译错误。

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

答案 1 :(得分: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类。