我是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'
Run Code Online (Sandbox Code Playgroud)
我现在收到两条错误,我在评论中写道.如果您知道我的代码有什么问题,请分享您的想法并节省我的时间......
非常感谢你.
Ben*_*Ben 60
-- No instance for (Fractional Int) arising from a use of `/'
Run Code Online (Sandbox Code Playgroud)
据推测,这是来自这一行,而不是你的评论:
prim Div [Number a, Number b] = Number (a / b)
Run Code Online (Sandbox Code Playgroud)
a并且b是Int.除法运算符是(/) :: Fractional a => a -> a -> a(你可以通过启动ghci并输入:t (/),或通过在Hoogle上查找来找到它).
如果您还没有看到类似的类型Fractional a => a -> a -> a,您应该分两部分阅读:
Fractional aa -> a -> a这就像常规a -> a -> a类型一样,因此需要两种类型的参数,并返回相同类型的结果.添加Fractional a上下文的唯一区别是用于的类型a必须是Fractional类类的实例; 它不是任意类型的自由范围.
如果您还没有学习类型类,请不要担心.它们很容易掌握,但是当你刚刚开始时,你不应该深入研究它们; 你以后会得到他们的.
Int不是Fractional类型类的成员,因此/运算符不适用于Ints.
原因是常规数学除法不适用于这种类型的整数; 3 / 2必须要么给予1.5,在这种情况下它不适合类型Int -> Int -> Int,或给予1或2,在这种情况下,它将不是正确的数学除法.有一个div实现整数除法的功能,可以像a `div` b中缀表示法一样使用.
-- Couldn't match expected type `Exp' with actual type `Value'
Run Code Online (Sandbox Code Playgroud)
此消息是关于您自己的类型,在您编写的单个表达式中.并且实际的完整错误消息将为您提供有关表达式的哪个部分包含错误的更多上下文.只需从上到下按照它,自己检查事物的类型,错误很快就会突然出现.
在这种情况下,你到达这里:
Let [("x", (Literal (Number 2)))] (prim Add [(Variable "x"), (Variable "y")])
Run Code Online (Sandbox Code Playgroud)
Let需要两个参数,a [(String, Exp)]和an Exp.列表很好,但第二个参数是(prim Add [(Variable "x"), (Variable "y")]).甚至没有挖掘它的子结构,看它是否正确,prim有类型Op -> [Value] -> Value,所以没有办法它会给你一个Exp.
如何解决这个问题取决于你; 看起来你需要在整个表达/值区分上有一点重构.prim给你一个Value,你可以简单地应用包裹Literal来让你超越你所获得的类型错误,但是你遇到了prim应该采取a Op和a的问题[Value],但你似乎给了它一个Op和一个[Exp](包含变量).我认为你需要考虑使用prim计算原始应用程序的结果,使用Primitive构造函数Exp来表示原始应用程序和使用eval(在一个环境中)评估任意表达式(可能包含几个原始应用程序)之间的区别一个价值.
Pau*_*aul 25
您遇到的问题是Haskell具有不同的整数和"小数"除法函数.整数除法截断,小数除法不.而不是
prim Div [Number a, Number b] = Number (a / b)
Run Code Online (Sandbox Code Playgroud)
你想做什么
prim Div [Number a, Number b] = Number (a `div` b)
Run Code Online (Sandbox Code Playgroud)
错误消息实际意味着该函数(/)是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'
Run Code Online (Sandbox Code Playgroud)
第一个提供有关函数的信息(/):它告诉您它在类中Fractional.然后,当:i Int它向您显示所有实例时Int.请注意,Int不是一个实例Fractional,所以你不能用(/)同Int.
另一个提示:反引号(`)将函数转换为中缀运算符
a `div` b
Run Code Online (Sandbox Code Playgroud)
是相同的
div a b
Run Code Online (Sandbox Code Playgroud)