看起来并不像我想象的那么简单

neb*_*ffa 0 haskell

在Haskell中为一个单独的,简单的编程语言编写一个解释器的过程中 - 当我学习在Haskell中输入时,我发现自己在墙上撞墙.

我有两种自定义数据类型

data Expr
    = Var Var
    | NumE Int
    | NilE
    | ConsE Expr Expr
    | Plus Expr Expr
    | Minus Expr Expr
    | Times Expr Expr
    | Div Expr Expr
    | Equal Expr Expr
    | Less Expr Expr
    | Greater Expr Expr
    | Not Expr
    | Isnum Expr
    | And Expr Expr
    | Or Expr Expr
    | Head Expr
    | Tail Expr
    | Call String
    deriving (Show, Read)

data Val = Num Int | Nil | Cons Val Val
    deriving (Eq, Show, Read)
Run Code Online (Sandbox Code Playgroud)

我开始用函数interpret_expr编写用于解释这些选项的案例

interpret_expr :: Vars -> Expr -> Val
interpret_expr vars@(Vars a b c d) (NumE integer) = integer
Run Code Online (Sandbox Code Playgroud)

但是这个COMPLAINS它无法将预期类型'Val'与表达式'integer'中的实际类型'Int'匹配.但是说我把它变成了傻逼的东西

interpret_expr :: Vars -> Expr -> Val
interpret_expr vars@(Vars a b c d) (NumE 'a') = 'a'
Run Code Online (Sandbox Code Playgroud)

然后它在'a'处抱怨它不能将预期类型'Int'与实际类型'Char'匹配.现在它想要INT ?????? 我真的不知道该说什么,我真的认为这就像为NumE提供一个它可能是一个整数的变量一样简单.我究竟做错了什么?

Sco*_*son 5

在第一种情况下,您Int将从声明为返回a的函数返回一个Val.从你的定义Val看起来你可能想回到Num integer这里.

在第二种情况下,问题在于模式匹配.(NumE 'a')是一个错误,因为NumE被定义为NumE Int,所以它必须后跟一个Int,而不是一个Char.

  • @nebffa是的,因为类型推断的工作方式.所有它知道的是`interpret_expr`的返回类型和`integer`的类型应该是相同的但它们不是,但它不知道哪一个是错的. (9认同)
  • Haskell的错误信息最初令人困惑.你很快习惯了它们. (2认同)
  • @nebffa,是的 - 虽然不是两个.擅长经常指向正确的位置,但并非总是如此.看看它指向的标识符的其他用途. (2认同)
  • @nebffa:将它视为"方孔中的圆钉"错误可能会有所帮助.GHC不知道哪个(如果有的话)是正确的形状,它只是知道它们不适合在一起.在第一种情况下,你将一个"Int"形状的钉子放在一个"Val"形孔中作为表达式的值; 在第二种情况下,你的模式匹配表示你想在一个"Int"形孔中形成一个"Char"形的钉子作为参数."实际"类型是peg(表达式),"预期"类型是孔(表达式使用的上下文). (2认同)