2016-01-06 78 views
0

我想写一个简单的递归函数来帮助我检查数学问题的某些值,但似乎无法添加任何有效的输入。无法输入值到函数中,因为无法推导出类型

这里是有问题的功能

fun 1 = 1 
fun n = fun (ceiling n) + 3 

这似乎是类型(Integral a1, Num a, RealFrac a1) => a1 -> a

给予fun任意数量的输入产生以下错误:

Could not deduce (Integral a10) arising from a use of ‘fun’ 
    from the context (Num a) 
     bound by the inferred type of it :: Num a => 

回答

3

看推断出的类型签名,你有Integral a1RealFrac a1作为约束条件,整体功能只返回Num a。你所说的是,这个函数的类型既是Integral也是RealFrac,这在逻辑上已经是一个矛盾,但在技术上可以在Haskell中实现,并返回任何数字类型。这来自您使用ceiling,其类型为(Integral b, RealFrac a) => a -> b,然后再次传递给fun。所以n必须是Integral,但由于您将ceiling n的结果传递给fun,因此它也必须是RealFrac。第二个问题是你根本没有给编译器足够的信息来确切地知道你想要使用哪种类型。

我的第一个建议是给fun输入你认为应该有的签名,我猜可能是Double -> Int。如果你这样做,你会得到一个No instance for (Integral Double) arising from use of ceiling ...的类型错误,这意味着你试图使用Double作为IntegralDouble由于显而易见的原因没有实现Integral。这告诉你,你的定义的哪一部分是可疑的。您可以选择使用fromIntegralfromIntegerceiling的结果转换为Double

除此之外,除非使用值1调用此函数,否则此函数将永不终止。它基本上只是建立一个反复加入3的巨大优势,并且会吃掉RAM和CPU。

+0

好吧,函数的定义是它在数学问题中的方式,所以如果它从不碰1,那就是为什么 –

1

这是因为ceiling返回Integral,并且您正在递归调用fun与价值,因此它推断fun必须接受Integral值,但ceiling需要RealFrac值,和你传递给ceiling你的fun应用得到了论证,因此它推断fun还必须采取RealFrac值。因此,约束。

在这样的情况下,最好在类型推断过程中通过用你认为应该有的类型注释你的函数来限制Haskell所考虑的选项 - 错误消息将变得更加具体/缩小,然后将更加本地化问题所在的代码;否则,类型推断将分析你的整个程序并考虑太多选项。

(也是函数本身是不明确的为对方的回答指出,但不会导致类型错误,很明显)

相关问题