#haskell #abstract-syntax-tree
#haskell #абстрактное синтаксическое дерево
Вопрос:
(Пожалуйста, заранее простите меня за любые ошибки форматирования, поскольку я впервые задаю здесь вопрос.)
Я работаю над интерпретатором языка While для класса, и я думаю, что у меня есть довольно хорошее представление об идеях, стоящих за этим, и о том, что мне нужно сделать. Для нас был предоставлен некоторый код (функции eval для типа Expr), и мы должны реализовать eval для типа оператора и функции поиска символов для присваиваний.
Моя текущая проблема заключается в том, что я получаю ошибки типа при попытке выполнить вышеуказанное, и я не уверен, почему.
Вот соответствующий код (обратите внимание, что значение While eval в данный момент намеренно установлено в = 0):
data Expr = Num Integer
| Var String
| Bin Op Expr Expr deriving Show
data Statement = Assign String Expr
| If Expr Statement Statement
| While Expr Statement
| Compound [Statement] deriving Show
env = [("n",1), ("fact", 1)]
eval (Num x) _ = x
eval (Var v) e = xlookup v e
where xlookup v ((w, x):r) | v==w = x
| otherwise = xlookup v r
eval (Bin op l r) e = kop op (eval l e) (eval r e)
where kop Mul x y = x * y
kop Sub x y = x - y
kop Add x y = x y
kop Gt x y | x > y = 1
| otherwise = 0
eval (While exp s) e = 0
factorial = (Compound [
(Assign "n" (Num 7)),
(Assign "fact" (Num 1)),
(While (Bin Gt (Var "n") (Num 1))
(Compound [
(Assign "fact" (Bin Mul (Var "fact") (Var "n"))),
(Assign "n" (Bin Sub (Var "n") (Num 1)))
])
)
])
Вот что я получаю:
Hugs> :l while.hs
ERROR "while.hs":37 - Type error in function binding
*** Term : eval
*** Type : Statement -> [([Char],Integer)] -> Integer
*** Does not match : Expr -> [([Char],Integer)] -> Integer
По сути, при каждой попытке, которую я делаю с функцией eval для оператора, Haskell, похоже, ожидает вместо этого Expr, и я не уверен, почему. Я уверен, что это очень простой вопрос, но, к сожалению, я очень новичок в Haskell и, по-видимому, все еще довольно ужасен в этом. Спасибо за любую помощь.
Ответ №1:
Вам либо нужно создать eval
метод класса типов, который, я думаю, на данный момент излишен, либо создать отдельные функции eval для ваших типов Expr и Statement:
eval_expr (Num x) = ...
eval_expr (Var x) = ...
eval_expr (Bin op l r) = ...
eval_stmt (While expr x) = ...
Метод typeclass будет выглядеть следующим образом:
class Eval a where
eval :: a -> [([Char], Integer)] -> Integer
instance Eval Expr where
eval (Num x) = ...
...
instance Eval Statement where
eval (While expr x) = ...
Комментарии:
1. Спасибо, это было очень полезно. Я сделал некоторые предположения о перегрузке функций, которые, по-видимому, были неточными! Я думаю, что в этом случае сработает любой способ, поэтому я подумаю над этим еще немного.
Ответ №2:
Первые три уравнения для eval
принимают an Expr
и environment, но While
являются конструктором типа Statement
. Таким образом, определения, которые вы даете, несовместимы. Вероятно, вам понадобятся две функции вычисления, одна для выражений, а другая для операторов. Если вы дадите сигнатуры типов ваших определений, вы получите лучшие (например, более понятные) сообщения об ошибках в целом.
Комментарии:
1. Спасибо, это было очень полезно. Я не знал, как дать eval сигнатуру типа из-за разных типов, которые я пытался передать; оглядываясь назад, это, вероятно, должно было быть подсказкой.