2016-04-28 47 views
1

Haskell "No instance for" error没有实例(成双)从使用 'REM' 的产生

Haskell Error: "No instance for (Enum [Int])

Function definition problems (No instance for … arising from)

No instance for Num String arising from the literal `1'

我是很新的哈斯克尔,和函数式编程一般来说。另外,我知道上面的问题非常类似,但我一直无法找到解决我的问题的任何地方。下面的代码是为了找到一些输入因素:

fc4 :: Double -> IO() 
check :: Double -> Double -> IO() 
fc4 a = check a (sqrt a) 
check a b = if rem a b == 0 then print (b, div a b) else print() >> if b > 1 then check a (b-1) else putStrLn ("Done.") 

我已经尝试切换从DoubleInteger和背部与每一个可能的组合,但是每一个失败,出现同样的错误:

No instance for (Integral Double) arising from a use of 'rem' 

我也尝试明确使用fromIntegraltoInteger上的参数rem,但没有尝试过的组合已经避免了这个问题。我还通过文档看到,rem的类型为Integral a => a -> a -> a,所以似乎使用相同类型的ab总能正常工作,无论是Double还是Integer

我在做些什么?我是否犯过一些可怕的菜鸟错误?作为参考,here是我希望实现的C++版本。提前致谢!

回答

5

你可以简单地在类型签名Integer更换Double,因为你需要使用其类型为Integral类型的类,它定义divrem实例的值。但是,sqrt只返回作为Floating类型实例的值,并且没有任何类型的实例都是。

简单的解决方案是使用ceiling来得到一个整数值,它只比sqrt n略大,这不会影响算法的正确性。

check :: Integer -> Integer -> IO() 
check a b = ... -- same as before 

fc4 :: Integer -> IO() 
--fc4 a = check a (ceiling (sqrt a)) -- because I didn't bother testing 
fc4 a = check a (floor (sqrt (fromIntegral a))) 
+0

非常感谢!这工作得很好,但我需要在'sqrt'中使用'fromIntegral'。 – StardustGogeta

+1

再次感谢!这甚至比预期的好!随着您的改进,我甚至可以完全删除类型签名声明。然而,我意识到我需要将'ceiling'改为'floor',以避免在找到6个因子时重复(2,3)。 – StardustGogeta

+1

@StardustGogeta,通常认为Haskell风格使用* all * top的类型签名级绑定。将它们用于本地绑定通常也是有帮助的。有一些相对不寻常的情况,其中类型签名可以延伸到几条线并且完全不可读,但是你远远不在那里。即便如此,最近添加的“PartialTypeSignatures”扩展可以让您写出一个签名,而不需要所有的细节。 – dfeuer

相关问题