Haskell 没有因使用`/';

Haskell 没有因使用`/';,haskell,Haskell,我是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

我是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'
导入数据。可能吧
数据Op=Add | Sub | Mul | Div | And | Or | Not | Eq | Less | Great
推导(等式,显示)
数据Exp=文字值
|基本运算[Exp]
|变量字符串
|如果Exp
|Let[(字符串,Exp)]Exp
推导(显示,等式)
数据值=整数
|布尔布尔布尔
|串
推导(等式,显示)
类型Env=[(字符串,值)]
评估::环境->经验->价值
评估e(文字v)=v
eval e(变量x)=fromJust(查找x e)--22
prim::Op->[Value]->Value
原始添加[编号a,编号b]=编号(a+b)
prim和[Bool a,Bool b]=Bool(a&b)
prim Sub[Number a,Nuamber b]=Number(a-b)--使用“/”不会产生(分数整数)的实例
prim Mul[编号a,编号b]=编号(a*b)
prim Div[编号a,编号b]=编号(a/b)
一本正经的或[Bool a,Bool b]=Bool(a | | b)
prim Not[Bool a]=Bool(Not a)
原始等式[数字a,数字b]=Bool(a==b)
prim Eq[String a,String b]=Bool(a==b)
prim Less[数字a,数字b]=Bool(ab)
原始的伟大[字符串a,字符串b]=Bool(a>b)--37
main=do
eval[((“y”,“数字40”)](Let[(“x”,“文字(数字2)))](prim Add[(变量“x”),(变量“y”))))——无法将预期类型“Exp”与实际类型“Value”匹配
我现在得到两个错误,我写在评论。 如果你知道我的代码有什么问题,请分享你的想法并节省我的时间


非常感谢。

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

prim Div [Number a, Number b] = Number (a / b)
你想做什么

prim Div [Number a, Number b] = Number (a `div` b)
错误消息实际上意味着函数
(/)
分数类的一部分。这基本上是一个不同类型可以实现的接口。要获取相关信息,请启动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'
第一个函数提供有关函数
(/)
的信息:它告诉您它在类
中。然后当您
:i Int
时,它会显示
Int
的所有实例。请注意,
Int
不是
fractive
的实例,因此不能将
(/)
Int
一起使用

另一个技巧:倒勾(`)将函数转换为中缀运算符,以便

a `div` b

div a b
大概是这句话,而不是你的评论:

prim Div [Number a, Number b] = Number (a / b)
a
b
Int
s。除法运算符是
(/)::分数a=>a->a->a
(您可以通过启动ghci并输入
:t(/)
,或通过以下方式找到答案)

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

  • 上下文
    分数a
  • 类型
    a->a->a
  • 这就像一个常规的
    a->a->a
    类型,因此它接受某个类型的两个参数,并返回相同类型的结果。添加
    分数a
    上下文的唯一区别是
    a
    使用的类型必须是
    分数
    类型类的实例;它不能自由地覆盖你喜欢的任何类型

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

    Int
    不是
    fractive
    类型类的成员,因此
    /
    运算符不适用于
    Int
    s

    原因是常规的数学除法对这种类型的整数不起作用
    3/2
    必须给出
    1.5
    ,在这种情况下,它不适合类型
    Int->Int->Int
    ,或者给出
    1
    2
    ,在这种情况下,它不是正确的数学除法。有一个用于实现的函数
    div
    ,类似于中缀符号中的
    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[(变量“x”),(变量“y”)))
    。甚至没有深入研究它的子结构来查看它是否正确,
    prim
    的类型是
    Op->[Value]->Value
    ,所以它不可能给你一个
    Exp

    如何解决这个问题取决于你;看起来您需要对整个表达式/值进行一点重构
    prim
    为您提供了一个
    值,您可以简单地应用
    文本中的wrap来克服您遇到的类型错误,但随后您遇到了一个问题,
    prim
    应该接受一个
    Op
    和一个
    [Value]
    ,但您似乎已经给了它一个
    Op
    [Exp]
    (包含变量)。我认为您需要考虑使用
    prim
    计算原始应用程序的结果、使用
    Exp
    primitive
    构造函数表示原始应用程序和使用
    eval
    计算(在环境中)任意表达式之间的区别(可能包含多个基本应用程序)转换为一个值。

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