【问题标题】:haskell division type mismatch?haskell 除法类型不匹配?
【发布时间】:2010-12-06 09:09:08
【问题描述】:

我是 Haskell 的新手,我正在尝试为家庭作业实现一个计算器。我被困在一个需要对两个值进行除法的地方,我认为问题是它们的类型无法推断或需要声明/转换。我正在尝试学习如何自己解决此问题,但在此过程中的任何见解都会有所帮助。

代码如下:

data Value e = OK e | Error String deriving (Eq)

-- assuming we know how to type e can be shown, i.e. Show e, then
-- we know how to show a Value e type
instance (Show e) => Show (Value e) where
    show (OK x) = (show x)
    show (Error s) = "ERROR: " ++ s

type Token = String
type Result = Value Int
type Intermediate = [ (Value Int) ]

-- an algebra is a things that knows about plus and times
class Algebra a where
    plus :: a -> a -> a
    times :: a -> a -> a
    subtraction :: a -> a -> a
    division :: a -> a-> a

-- assuming that we know how to + and * things of type e, (i.e.
-- we have Num e, then we have algebra's over Value e 
instance (Num e) => Algebra (Value e) where
    plus (OK x) (OK y) = (OK (x+y))
    times (OK x) (OK y) = (OK (x*y))
    subtraction (OK x) (OK y) = (OK (x-y))
    division (OK x) (OK 0) = (Error "div by 0")
    division (OK x) (OK y) = (OK (x `div` y))   <-- this is line 44 that it complains about

这是我尝试通过 ghci test.hs 运行程序时出现的错误

test.hs:44:34:  
    Could not deduce (Integral e)  
      from the context (Algebra (Value e), Num e)  
      arising from a use of `div' at test.hs:44:34-42  
    Possible fix:  
      add (Integral e) to the context of the instance declaration  
    In the first argument of `OK', namely `(x `div` y)'  
    In the expression: (OK (x `div` y))  
    In the definition of `division':  
        division (OK x) (OK y) = (OK (x `div` y))  

还有更多代码,我想为了清楚起见我会省略它,但如果不清楚,我总是可以编辑它。

【问题讨论】:

  • 这不应该是个问题..

标签: haskell types typeclass


【解决方案1】:
div :: (Integral a) => a -> a -> a
(/) :: (Fractional a) => a -> a -> a

Num a 既不暗示Integral a 也不暗示Fractional a(当然反过来也适用)。如果您想使用div,您必须提供至少与Integral a 上下文一样严格的内容。

【讨论】:

  • ... 我不敢相信我花了这么长时间,我一直在寻找所有错误的地方,试图限制使用 e 的类型。你指出 Num 让我找到了 instance (Num e) =&gt; 可能是我在测试期间没有考虑更改的唯一一行代码......谢谢
【解决方案2】:

div 仅对 Integral 值起作用(仅在标准 Prelude 中为 IntInteger)。 FloatDouble 支持使用 / 运算符进行除法,但问题的根源在于 Num 类型类实际上并不要求进行任何类型的除法运算。

这是有道理的——有很多数字集合我们可能想要创建 Num 的实例,其中乘法是不可逆的——除法运算基本上没有意义。

【讨论】:

    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 2016-02-01
    • 2013-05-04
    • 2018-03-16
    • 1970-01-01
    • 2014-10-17
    相关资源
    最近更新 更多