Haskell: как оценить строку типа «1 + 2» - PullRequest
9 голосов
/ 07 апреля 2011

На самом деле у меня есть некоторая формула, такая как "x + y", которая является String.Мне удалось заменить переменную x/y конкретными значениями, такими как "1.2", который по-прежнему String типа.Теперь у меня есть выражение вроде "1 + 2".

. Итак, проблема в том, как оценить выражение строкового типа и получить результат.

ps: я хочу что-то вроде read, чтоможет напрямую преобразовывать целое строковое выражение вместо обработки оператора (+/- и т. д.) в каждом конкретном случае.Это возможно?

Ответы [ 3 ]

19 голосов
/ 07 апреля 2011

Ваш вопрос оставляет много места для интерпретации.Я предполагаю, что вы не привыкли к созданию целого конвейера лексирования, синтаксического анализа, возможно проверки типов и оценки.Длинный ответ будет включать в себя определение того, какой язык вы хотите оценить (просто целые числа с «+», возможно, все рациональные числа с «+», «-», «*», «/» или даже больший язык?) И выполнение каждого из них.из приведенных выше шагов для этого языка.

Краткий ответ: для оценки выражений на языке Haskell, включающих основные математические операторы, о которых вы, вероятно, говорите, просто используйте пакет "подсказка":

$ cabal install hint
...
$ ghci
> import Language.Haskell.Interpreter
> runInterpreter $ setImports ["Prelude"] >> eval "3 + 5"
Right "8"

Ууу!

5 голосов
/ 07 апреля 2011

Может быть стоит прочитать раздел Парсек Real World Haskell .Вы можете проанализировать его в дереве выражений и затем подставить значения в него. По мере использования Parsec вы будете строить дерево выражений с использованием типов (очень грубо, я уверен, что допустил некоторые ошибки, которые я исправлю в исправлениях).как и когда люди указывают на них!) как показано ниже.

 data Op = Plus | Minus
 data Term = Variable String
           | Value Int
 data Expression = Expr Expression Op Expression
                 | Term

Тогда 1 + 2 будет (Expr (Variable "x") Plus (Variable "y")), и вы можете применить соответствующие замены.

Чтобы получить результатЯ думаю, вы могли бы исправить простую функцию evaluate :: Map String Int -> Expression -> Either ErrorMessage Int, которая будет применять привязки на карте, а затем вычислять результат, если это возможно.

2 голосов
/ 07 апреля 2011

Ну, я бился головой о намек , но сейчас я сдаюсь. Я знаю, что подсказка может сделать это, но я не знаю, как. [править] См. Ответ TomMD о том, как настроить импорт для подсказки. [/ edit ]

import Language.Haskell.Interpreter (eval, runInterpreter, Interpreter, InterpreterError)

main = do let resIO = eval "3" :: Interpreter String
          res <- runInterpreter resIO
          print res

Это неинтересно выдает Right "3" в результате. Я пробовал следующие варианты, только чтобы столкнуться с ошибками:

... eval "3 + 3" ....
-- yields --
Left (WontCompile [GhcError (errMsg = "Not in scope: `+'"])

Оператор + не находится в области видимости ??? WTF ...

import Language.Haskell.Interpreter (interpret, as, runInterpreter, Interpreter)

main = do let resIO = interpret "3" (as :: Int) :: Interpreter Int
          res <- runInterpreter resIO
          print res
-- yields --
Left (WontCompile [GhcError (errMsg = "Not in scope: type constructor or class 'Int'")])

Класс Int не находится в области видимости ??? тьфу ...

Я приглашаю тех, кто более осведомлен, чем я, излагать более тонкие детали подсказки.

...