我正在尝试编写一些代码,通过试验除法对整数进行完全分解。这段代码似乎应该起作用:
findAFact :: Integral x => x -> x
findAFact x = searchInts [2, 3..] x where
searchInts (int:ints) div
| div `mod` int == 0 = int
| otherwise = searchInts ints div
completeFacts :: Integral x => x -> [x]
completeFacts x = tryForFact [] x where
tryForFact fs x = if x == 1
then fs
else let fact = findAFact x
in tryForFact (fact:fs) (floor ((fromIntegral x) / fact))
但是,如果我尝试对此进行编译,则会出现以下错误:
Could not deduce (RealFrac x) arising from a use of 'tryForFact'
from the context (Integral x)
bound by the type signature for
completeFacts :: Integral x => x -> [x]
at 5.hs:26:18-39
Possible fix:
add (RealFrac x) to the context of
the type signature for completeFacts :: Integral x => x -> [x]
In the expression: tryForFact [] x
In an equation for 'completeFacts':
completeFacts x
= tryForFact [] x
where
tryForFact fs x
= if x == 1 then
fs
else
let ... in tryForFact (fact : fs) (floor ((fromIntegral x) / fact))
如果我从中删除类型签名completeFacts
并尝试将其加载到GHCI中,则解释器将加载文件并(RealFrac x, Integral x ) => x -> [x]
为其提供类型签名completeFacts
,但是当我尝试使用completeFacts
该方法时会抱怨show
,因为在的上下文中其类型不明确,因此无法使用它show
。这对我来说很有意义,因为似乎有一种清晰的方法将x显示为aRealFrac
或an Integral
,但不能同时显示两者。
这似乎是令人反感的代码:
...
in tryForFact (fact:fs) (floor ((fromIntegral x) / fact))
我很困惑,因为我想象过将xfromIntegral
传递给然后将除法的结果传递floor
给我会得到Integral
回报。我不明白为什么Haskell仍然认为x还需要具有类型类RealFrac
。Haskell为什么坚持这一点,以及如何重写才能completeFacts
使x只能是an Integral
?
谢谢!
这是因为您在进行除法运算之前没有转换fact
为RealFrac
:
in tryForFact (fact:fs) (floor (fromIntegral x / fromIntegral fact))
您已经说过了fact = findAFact x
,它具有类型Integral x => x
,但是您正在将其与一起使用/
,因此它认为它需要同时满足Integral
和RealFrac
。
实际上更好的方法是使用它div
(我也对代码进行了一些整理,以使它更易于阅读,并且您不会在现有的绑定上留下阴影x
):
completeFacts :: Integral x => x -> [x]
completeFacts x = tryForFact [] x
where
tryForFact fs 1 = fs
tryForFact fs y = let fact = findAFact y
in tryForFact (fact:fs) (y `div` fact)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句