没有因使用 `/' 而产生的 (Fractional Int) 实例 [英] No instance for (Fractional Int) arising from a use of `/'

查看:19
本文介绍了没有因使用 `/' 而产生的 (Fractional Int) 实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to Haskell, and I am struggling with debugging my code. Fixing an error leads to other errors...

这是我的代码.

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'

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

I am now getting two errors which I wrote in comments. If you know what's wrong with my code, please share your idea and save my time...

非常感谢.

推荐答案

-- No instance for (Fractional Int) arising from a use of `/'

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

Presumably that's coming from this line rather than the one with your comment:

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

abInts.除法运算符是 (/) :: Fractional a =>->->a(您可以通过启动 ghci 并输入 :t (/)在 Hoogle 上查找).

a and b are Ints. The division operator is (/) :: Fractional a => a -> a -> a (you can find that out by firing up ghci and entering :t (/), or by looking it up on Hoogle).

如果你还没有见过像 Fractional a => 这样的类型->->a,你应该分两部分阅读:

If you haven't seen types like Fractional a => a -> a -> a, you should read this in two parts:

  1. 上下文分数a
  2. 类型 a ->->一个

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

This is just like a regular a -> a -> a type, so it takes two arguments of some type and gives you back a result of the same type. The only difference in adding the Fractional a context is that type used for a must be an instance of the Fractional type class; it isn't free to range over any type you like.

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

If you haven't learned about type classes yet don't worry. They're pretty easy to grasp, but not something you should be looking at in depth when you're just starting; you'll get to them later.

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

Int isn't a member of the Fractional type class, so the / operator doesn't work on Ints.

原因是常规数学除法不适用于这种类型的整数;3/2 要么给 1.5,在这种情况下它不适合 Int ->内部 ->Int,或者给 12,在这种情况下,它不是正确的数学除法.有一个函数 div 用于实现 整数除法,像中缀表示法中的a `div` b一样使用.

The reason is that regular mathematical division doesn't work on integers with this type; 3 / 2 would have to either give 1.5, in which case it doesn't fit the type Int -> Int -> Int, or give 1 or 2, in which case it wouldn't be correct mathematical division. There is a function div for implementing integer division, usable like a `div` b in infix notation.

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

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

This message is about your own types, in a single expression you wrote. And the actual full error message would have given you more context about which part of the expression contains the error. Just follow it through from the top down, checking the types of things yourself and the error very quickly leaps out at you.

在这种情况下,您可以访问此处:

In this case, you get to here:

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

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

Let needs two arguments, a [(String, Exp)] and an Exp. The list is fine, but the second argument is (prim Add [(Variable "x"), (Variable "y")]). Without even digging into the substructure of that to see if it's correct, prim has type Op -> [Value] -> Value, so there's no way it's going to give you an Exp.

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

How to fix that is up to you; it looks like you need a bit of a refactor across the whole expression/value distinction. prim gives you an Value, which you could simply apply wrap in a Literal to get you past the type error you're getting, but then you run into the problem that prim should be taking an Op and a [Value], but you appear to have given it an Op and a [Exp] (containing variables). I think you need to think about the difference between using prim to compute the results of a primitive application, using the Primitive constructor of Exp to represent a primitive application, and using eval to evaluate (in an environment) an arbitrary expression (which may contain several primitive applications) to a value.

这篇关于没有因使用 `/' 而产生的 (Fractional Int) 实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆