Функция анализа в haskell
Я новичок в Haskell, и я пытаюсь разобрать выражения. Я узнал о Parsec, и я также нашел несколько статей, но, похоже, я не понимаю, что мне нужно делать. Моя проблема в том, что я хочу дать выражение типа "x ^ 2 + 2 * x + 3", а результат - это функция, которая принимает аргумент x и возвращает значение. Мне очень жаль, если это простой вопрос, но мне действительно нужна помощь. Благодарю! Код, который я вставил, из статьи, которую вы можете найти на этой ссылке.
import Control.Monad(liftM)
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec.Token
import Text.ParserCombinators.Parsec.Language
data Expr = Num Int | Var String | Add Expr Expr
| Sub Expr Expr | Mul Expr Expr | Div Expr Expr
| Pow Expr Expr
deriving Show
expr :: Parser Expr
expr = buildExpressionParser table factor
<?> "expression"
table = [[op "^" Pow AssocRight],
[op "*" Mul AssocLeft, op "/" Div AssocLeft],
[op "+" Add AssocLeft, op "-" Sub AssocLeft]]
where
op s f assoc
= Infix (do{ string s; return f}) assoc
factor = do{ char '('
; x <- expr
; char ')'
; return x}
<|> number
<|> variable
<?> "simple expression"
number :: Parser Expr
number = do{ ds<- many1 digit
; return (Num (read ds))}
<?> "number"
variable :: Parser Expr
variable = do{ ds<- many1 letter
; return (Var ds)}
<?> "variable"
Ответы
Ответ 1
Это просто парсер для выражений с переменными. Фактически интерпретация выражения является совершенно отдельным вопросом.
Вы должны создать функцию, которая принимает уже разобранное выражение и значения для переменных, и возвращает результат вычисления выражения. Псевдокод:
evaluate :: Expr -> Map String Int -> Int
evaluate (Num n) _ = n
evaluate (Var x) vars = {- Look up the value of x in vars -}
evaluate (Plus e f) vars = {- Evaluate e and f, and return their sum -}
...
Я преднамеренно опустил некоторые подробности; надеюсь, исследуя недостающие части, вы узнаете больше о Haskell.
В качестве следующего шага вам, вероятно, следует взглянуть на монаду Reader
для удобного способа передачи карты переменных vars
вокруг и с помощью Maybe
или Error
для сигнализации ошибок, например. ссылаясь на переменную, которая не связана в vars
, или деление на ноль.