英文:
How can I resolve an ambigious type runtime error in haskell?
问题
我有一个Haskell函数,它计算给定位置的无限列表中的数字:
[2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,...]
因此,对于第n个新数字,列表将是l(n-1) ++ [n] ++ l(n-1)。
我已经实现了这个函数:
getNumb theta = if ((floor (logBase 2 theta)) == ceiling (logBase 2 theta))
then (floor (logBase 2 theta)) + 2
else getNumb (2*(floor (logBase 2 theta)) - theta)
但是,当我像这样运行它:getNumb 10
时,我收到了以下错误:
<interactive>:3:1: error:
* Could not deduce (RealFrac t0) arising from a use of `getNumb'
from the context: Integral p
bound by the inferred type of it :: Integral p => p
at <interactive>:3:1-10
The type variable `t0' is ambiguous
These potential instances exist:
instance RealFrac Double -- Defined in `GHC.Float'
instance RealFrac Float -- Defined in `GHC.Float'
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: getNumb 10
In an equation for `it': it = getNumb 10
<interactive>:3:9: error:
* Could not deduce (Num t0) arising from the literal `10'
from the context: Integral p
bound by the inferred type of it :: Integral p => p
at <interactive>:3:1-10
The type variable `t0' is ambiguous
These potential instances exist:
instance Num Integer -- Defined in `GHC.Num'
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
...plus two others
...plus two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `getNumb', namely `10'
In the expression: getNumb 10
In an equation for `it': it = getNumb 10
据我理解,问题在于函数的返回类型与输入类型不兼容。这是正确的吗?如果是的话,我该如何修复它?
注意:这是:t
的输出,据说返回一个Integer
是正确的。
*Main> :t getNumb
getNumb
:: (RealFrac t, Floating t, Integral p, Integral t) => t -> p
英文:
I have this haskell function which calculates the number in a given position of this infinite list:
[2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,...]
So for the n-th new number the list would be l(n-1) ++ [n] ++ l(n-1).
I have implemented this function:
getNumb theta = if ((floor (logBase 2 theta)) == ceiling (logBase 2 theta))
then (floor (logBase 2 theta)) + 2
else getNumb (2*(floor (logBase 2 theta)) - theta)
but when I run it like this: getNumb 10
I get this error:
<interactive>:3:1: error:
* Could not deduce (RealFrac t0) arising from a use of `getNumb'
from the context: Integral p
bound by the inferred type of it :: Integral p => p
at <interactive>:3:1-10
The type variable `t0' is ambiguous
These potential instances exist:
instance RealFrac Double -- Defined in `GHC.Float'
instance RealFrac Float -- Defined in `GHC.Float'
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: getNumb 10
In an equation for `it': it = getNumb 10
<interactive>:3:9: error:
* Could not deduce (Num t0) arising from the literal `10'
from the context: Integral p
bound by the inferred type of it :: Integral p => p
at <interactive>:3:1-10
The type variable `t0' is ambiguous
These potential instances exist:
instance Num Integer -- Defined in `GHC.Num'
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
...plus two others
...plus two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `getNumb', namely `10'
In the expression: getNumb 10
In an equation for `it': it = getNumb 10
As far as I understand the problem lies in the return type of the function which is not compatible with the input type. Is this correct? If yes how do I fix it?
Note: This the output of :t
and supposedly it is correct to return an Integer
*Main> :t getNumb
getNumb
:: (RealFrac t, Floating t, Integral p, Integral t) => t -> p
答案1
得分: 2
计算对数是一种低效的方法来找到这个值。相反,沿着“树”的路径向下工作,并在返回时计算索引。这只需要对参数施加一个Integral
约束,因为除了将其除以2之外,你不会做任何其他操作。
请注意,所有偶数索引都计算为2;奇数索引会递归计算。
getNumb theta | even theta = 2
| otherwise = 1 + getNumb (theta `quot` 2)
even
是基于rem
实现的,而quot
和rem
都只是quotRem
的包装器,所以你可以考虑直接调用quotRem
自己。
getNumb theta = case quotRem theta 2 of
(_, 0) -> 2
(q, _) -> 1 + getNumb q
作为这个方法有效性的证明,注意你可以将这个函数映射到自然数上,以获得原始列表:
> map getNumb [0..30]
[2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2]
英文:
Computing logarithms is an inefficient way to find the value. Instead, work your way down the "tree", and compute the index on the way back up. This requires only an Integral
constraint on the argument, since you never do anything except divide it by 2.
Note that all even indices evaluate to 2; the odd ones are computed recursively.
getNumb theta | even theta = 2
| otherwise = 1 + getNumb (theta `quot` 2)
even
is implemented in terms of rem
, and both quot
and rem
are just wrappers around quotRem
, so you might want to simply call quotRem
yourself.
getNumb theta = case quotRem theta 2 of
(_, 0) -> 2
(q, _) -> 1 + getNum q
As proof that this works, note that you can map the function over the natural numbers to get back the original list:
> map getNumb [0..30]
[2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论