Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 没有因使用“rem”而产生的(二重积分)实例_Haskell - Fatal编程技术网

Haskell 没有因使用“rem”而产生的(二重积分)实例

Haskell 没有因使用“rem”而产生的(二重积分)实例,haskell,Haskell,我对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 the

我对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.")
我尝试过用各种可能的组合从Double切换到Integer,然后再切换回来,但每一个都失败了,出现了相同的错误:

No instance for (Integral Double) arising from a use of 'rem'
我也尝试过在rem的参数上显式地使用fromIntegral和toInteger,但我尝试的任何组合都无法避免这个问题。我还从文档中看到rem的类型是Integral a=>a->a->a,因此似乎对a和b使用相同的类型总是有效的,无论是Double还是Integer

我知道什么了吗?我有没有犯过一些可怕的新手错误?仅供参考,是我希望实现的C++版本。提前谢谢

您可以在类型签名中简单地将Double替换为Integer,因为您需要使用一个值,该值的类型是Integral类型类的实例,该类定义div和rem。但是,sqrt只返回作为浮点类型类实例的值,并且没有任何类型同时作为这两个类的实例

简单的解决方案是使用天花板获得一个略大于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)))
您可以在类型签名中简单地将Double替换为Integer,因为您需要使用一个值,该值的类型是Integral类型类的实例,该类定义div和rem。但是,sqrt只返回作为浮点类型类实例的值,并且没有任何类型同时作为两者的实例

简单的解决方案是使用天花板获得一个略大于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)))

非常感谢你!这很好,但我需要在sqrt中使用fromIntegral。再次感谢!这比预期的还要好!通过您的改进,我甚至可以完全删除类型签名声明。然而,我意识到我需要将天花板改为地板,以避免在找到6的因子时重复2,3。@StardustGogeta,通常认为对所有顶级绑定使用类型签名是好的Haskell风格。在本地绑定中使用它们通常也很有帮助。在一些相对不寻常的情况下,类型签名可以扩展到几行,并且完全不可读,但您离这还很远。即使这样,最近添加的PartialTypeSignatures扩展也可以让您在编写签名时不必考虑所有混乱的细节。@dfeur非常感谢您让我知道这一点!再加上@dfeuer的注释,缺少类型签名会使错误消息更加难以理解,因为编译器真正能说的是代码中的某些内容与其他内容不一致,并且通常会猜测不一致的行中哪一行实际上是错误。非常感谢!这很好,但我需要在sqrt中使用fromIntegral。再次感谢!这比预期的还要好!通过您的改进,我甚至可以完全删除类型签名声明。然而,我意识到我需要将天花板改为地板,以避免在找到6的因子时重复2,3。@StardustGogeta,通常认为对所有顶级绑定使用类型签名是好的Haskell风格。在本地绑定中使用它们通常也很有帮助。在一些相对不寻常的情况下,类型签名可以扩展到几行,并且完全不可读,但您离这还很远。即使这样,最近添加的PartialTypeSignatures扩展也可以让您在编写签名时不必考虑所有混乱的细节。@dfeur非常感谢您让我知道这一点!要添加到@dfeuer的注释中,缺少类型签名会使错误消息更加难以理解,因为编译器真正能说的是代码中的某些内容与其他内容不一致,并且它通常会猜测不一致的行中哪一行实际上是错误的。