没有因使用 `/' 而产生的 (Fractional Int) 实例 [英] No instance for (Fractional Int) arising from a use of `/'
问题描述
我是 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)
a
和 b
是 Int
s.除法运算符是 (/) :: Fractional a =>->->a
(您可以通过启动 ghci 并输入 :t (/)
或 在 Hoogle 上查找).
a
and b
are Int
s. 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:
- 上下文
分数a
- 类型
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
类型类的成员,因此 /
运算符不适用于 Int
s.
Int
isn't a member of the Fractional
type class, so the /
operator doesn't work on Int
s.
原因是常规数学除法不适用于这种类型的整数;3/2
要么给 1.5
,在这种情况下它不适合 Int ->内部 ->Int
,或者给 1
或 2
,在这种情况下,它不是正确的数学除法.有一个函数 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
来计算原始应用程序的结果之间的区别,使用 Exp
的 Primitive
构造函数到 代表一个原始应用程序,并使用 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屋!