没有使用'rem'产生的(Integral Double)实例

Sta*_*eta 1 haskell

Haskell"没有实例"错误

Haskell错误:"没有实例(Enum [Int])

函数定义问题(没有...的实例)

字符"1"中没有Num字符串的实例

我是Haskell的新手,也是一般的函数式编程.另外,我知道上面的问题非常相似,但我无法在任何地方找到解决问题的方法.以下代码用于查找数字输入的因子:

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.")
Run Code Online (Sandbox Code Playgroud)

我尝试使用每种可能的组合切换DoubleInteger和返回,但每个都失败并出现相同的错误:

No instance for (Integral Double) arising from a use of 'rem'
Run Code Online (Sandbox Code Playgroud)

我也试过明确地使用fromIntegraltoInteger参数rem,但我没有尝试避免这个问题.我还通过文档看到类型remIntegral a => a -> a -> a,所以似乎使用相同的类型a并且b将始终有效,无论是DoubleInteger.

我有事吗?我犯了一些可怕的菜鸟错误吗?作为参考,是我希望实现的C++版本.提前致谢!

che*_*ner 6

你可以简单地替换DoubleInteger的类型签名,因为你需要使用它的类型是实例的值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)))
Run Code Online (Sandbox Code Playgroud)

  • @StardustGogeta,通常将“类型签名”用于* all *顶级绑定是一种很好的Haskell风格。将它们也用于本地绑定通常也很有帮助。在某些相对不寻常的情况下,类型签名可能会扩展到多行并且完全不可读,但您离那里并不遥远。即使那样,最近添加的`PartialTypeSignatures`扩展名也可以让您编写没有所有混乱细节的签名。 (2认同)