【问题标题】:No instance for (Integral Double) arising from a use of 'rem'没有因使用“rem”而产生 (Integral Double) 的实例
【发布时间】:2016-04-28 11:25:09
【问题描述】:

Haskell "No instance for" error

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'

我是 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 的参数上显式使用fromIntegraltoInteger,但我尝试的任何组合都没有避免这个问题。我还从文档中看到rem 的类型是Integral a => a -> a -> a,因此似乎对ab 使用相同的类型总是有效的,无论是Double 还是Integer

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

【问题讨论】:

    标签: haskell


    【解决方案1】:

    您可以简单地将类型签名中的Double 替换为Integer,因为您需要使用类型为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)))
    

    【讨论】:

    • 非常感谢!这很有效,但我需要在sqrt 中使用fromIntegral
    • 再次感谢!这甚至比预期的还要好!随着您的改进,我什至可以完全删除类型签名声明。但是,我意识到我需要将 ceiling 更改为 floor 以避免在找到 6 的因数时重复 (2,3)。
    • @StardustGogeta,将类型签名用于 all 顶级绑定通常被认为是良好的 Haskell 风格。将它们用于本地绑定通常也很有帮助。有一些相对不寻常的情况,类型签名可以扩展到几行并且完全不可读,但你离那里很远。即便如此,最近添加的PartialTypeSignatures 扩展程序也可以让您编写签名,而不需要所有杂乱的细节。
    • @dfeuer 非常感谢您让我知道这件事!
    • 添加到@dfeuer 的评论中,缺少类型签名会使错误消息更加难以理解,因为编译器只能说您的代码中的某些内容与其他内容不一致,并且通常会猜错哪条不一致的行实际上是错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    相关资源
    最近更新 更多