【问题标题】:No instance for (Fractional Int) arising from a use of `/'没有因使用“/”而产生的 (Fractional Int) 实例
【发布时间】:2014-02-04 04:26:36
【问题描述】:

我是 Haskell 的新手,我正在努力调试我的代码。 修复一个错误会导致其他错误...

这是我的代码。

import Data.Maybe

data Op = Add | Sub | Mul | Div | And | Or | Not | Eq | Less | Great
    deriving (Eq, Show)

data Exp = Literal Value
     | Primitive Op [Exp]
     | Variable String
     | If Exp Exp Exp
     | Let [(String, Exp)] Exp
    deriving (Show, Eq)

data Value = Number Int
       | Bool Bool
       | String String
    deriving (Eq, Show)

type Env = [(String, Value)]

eval :: Env -> Exp -> Value
eval e (Literal v) = v
eval e (Variable x) = fromJust (lookup x e)   --22

prim :: Op -> [Value] -> Value
prim Add [Number a, Number b] = Number (a + b)
prim And [Bool a, Bool b] = Bool (a && b)
prim Sub [Number a, Nuamber b] = Number (a - b)   -- No instance for (Fractional Int) arising from a use of `/'
prim Mul [Number a, Number b] = Number (a * b)
prim Div [Number a, Number b] = Number (a / b)
prim Or [Bool a, Bool b] = Bool (a || b)
prim Not [Bool a] = Bool (not a)
prim Eq [Number a, Number b] = Bool (a == b)
prim Eq [String a, String b] = Bool (a == b) 
prim Less [Number a, Number b] = Bool (a < b)
prim Less [String a, String b] = Bool (a < b)
prim Great [Number a, Number b] = Bool (a > b)
prim Great [String a, String b] = Bool (a > b) --37

main = do
    eval [("y", (Number 40))] (Let [("x", (Literal (Number 2)))] (prim Add [(Variable "x"), (Variable "y")])) -- Couldn't match expected type `Exp' with actual type `Value'

我现在遇到了两个我在 cmets 中编写的错误。 如果您知道我的代码有什么问题,请分享您的想法并节省我的时间...

非常感谢。

【问题讨论】:

  • 您的意思是Number (div a b) 还是它的中缀版本?
  • 有一个拼写错误Nuamber 而不是Number

标签: haskell


【解决方案1】:
-- No instance for (Fractional Int) arising from a use of `/'

大概是来自这一行,而不是你的评论:

prim Div [Number a, Number b] = Number (a / b)

abInts。除法运算符是(/) :: Fractional a =&gt; a -&gt; a -&gt; a(您可以通过启动ghci 并输入:t (/)looking it up on Hoogle 来找到它)。

如果您还没有看到像 Fractional a =&gt; a -&gt; a -&gt; a 这样的类型,您应该分两部分阅读:

  1. 上下文Fractional a
  2. 类型a -&gt; a -&gt; a

这就像一个普通的a -&gt; a -&gt; a 类型,所以它接受两个某种类型的参数并返回一个相同类型的结果。添加Fractional a 上下文的唯一区别是用于a 的类型必须是Fractional 类型类的实例;它不能随意选择你喜欢的任何类型。

如果您还没有了解类型类,请不要担心。它们很容易掌握,但不是刚开始时应该深入研究的东西;您稍后会找到他们。

Int 不是Fractional 类型类的成员,因此/ 运算符不适用于Ints。

原因是常规数学除法适用于这种类型的整数; 3 / 2 必须要么给出1.5,在这种情况下它不适合Int -&gt; Int -&gt; Int 类型,要么给出12,在这种情况下它不是正确的数学除法。有一个函数div 用于实现integer division,可以像a `div` b 一样使用中缀表示法。

-- Couldn't match expected type `Exp' with actual type `Value'

此消息是关于您自己的类型的,在您编写的单个表达式中。并且实际的完整错误消息将为您提供有关表达式的哪个部分包含错误的更多上下文。只需从上到下,自己检查事物的类型,错误很快就会出现。

在这种情况下,你到这里:

Let [("x", (Literal (Number 2)))] (prim Add [(Variable "x"), (Variable "y")])

Let 需要两个参数,一个[(String, Exp)] 和一个Exp。列表很好,但第二个参数是(prim Add [(Variable "x"), (Variable "y")])。甚至没有深入研究它的子结构以查看它是否正确,prim 的类型为Op -&gt; [Value] -&gt; Value,所以它不可能给你一个Exp

如何解决这个问题取决于您;看起来您需要对整个表达式/值的区别进行一些重构。 prim 给你一个 Value,你可以简单地在 Literal 中应用 wrap 来解决你遇到的类型错误,但是你会遇到 prim 应该采用 @987654361 的问题@ 和 [Value],但您似乎给了它一个 Op 和一个 [Exp](包含变量)。我认为您需要考虑使用prim 计算原始应用程序的结果、使用ExpPrimitive 构造函数来表示原始应用程序和使用@987654368 之间的区别@ 将(在环境中)任意表达式(可能包含多个原始应用程序)评估为一个值。

【讨论】:

  • 非常感谢您抽出宝贵时间回答我的问题。
  • 对不起,这个“(/) :: Fractional a => a -> a -> a”是什么意思?这意味着它将 a 和另一个 a 作为参数并返回 a,对吗?但是a是什么意思?我怎么知道 Int 不是 Fractional 类型类的成员?
  • Paul 在他的回答中已经为您提供了一些很好的信息,但是由于您从错误消息No instance for (Fractional Int) 开始,GHC 已经告诉您Int 不是@ 的成员987654371@.
  • @dockbudu 我在关于Fractional a =&gt; a -&gt; a -&gt; a 类型的答案中添加了一些内容,希望对您有所帮助。
  • @Ben 哦,哇。你的解释说得很清楚。这绝对有帮助。谢谢你。我现在需要继续解决另一个问题。非常感谢。
【解决方案2】:

您遇到的问题是 Haskell 对整数和“小数”除法有不同的功能。整数除法会截断,小数除法不会。所以不是

prim Div [Number a, Number b] = Number (a / b)

你想做的

prim Div [Number a, Number b] = Number (a `div` b)

错误消息的实际含义是函数(/)Fractional 类的一部分。这基本上是一个不同类型可以实现的接口。要获取有关它的信息,请启动 ghci 并执行

Prelude> :i (/)
class Num a => Fractional a where
(/) :: a -> a -> a
...
-- Defined in `GHC.Real'
infixl 7 /

Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int#   -- Defined in `GHC.Types'
instance Bounded Int -- Defined in `GHC.Enum'
instance Enum Int -- Defined in `GHC.Enum'
instance Eq Int -- Defined in `GHC.Classes'
instance Integral Int -- Defined in `GHC.Real'
instance Num Int -- Defined in `GHC.Num'
instance Ord Int -- Defined in `GHC.Classes'
instance Read Int -- Defined in `GHC.Read'
instance Real Int -- Defined in `GHC.Real'
instance Show Int -- Defined in `GHC.Show'

第一个为您提供有关函数(/) 的信息:它告诉您它在类Fractional 中。然后当您:i Int 时,它会向您显示Int 的所有实例。请注意,Int 不是Fractional 的实例,因此您不能将(/)Int 一起使用。

另一个提示:反引号 (`) 将函数转换为中缀运算符,因此

a `div` b

一样
div a b

【讨论】:

  • 非常感谢,您对第二个错误有什么想法吗?
  • div 操作员为我炒锅
猜你喜欢
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多