Карта, которая связывает операторы с лямбда-функциями - PullRequest
3 голосов
/ 06 января 2011

У меня есть карта Haskell, содержащая строки в качестве ключей и некоторые лямбда-функции в качестве элементов.Например:

1002 *

Я хочу написать функцию, которая принимает в качестве входных данных:

  • Строка, представляющая оператор ["+", "-", "*","/"]
  • Два числа

На основе оператора и карты операций, функция будет оценивать сумму / вычитание / и т.д.из двух чисел.

Я пробовал что-то вроде:

(Map.lookup "+" a) 1 2

Но это не работает.

Ошибка:

Top level:
    No instance for (Show (Integer -> Integer))
      arising from use of `print' at Top level
    Probable fix: add an instance declaration for (Show (Integer
    In a 'do' expression: print it

<interactive>:1:1:
    No instance for (Monad ((->) t))
      arising from use of `Data.Map.lookup' at <interactive>:1:1-
    Probable fix: add an instance declaration for (Monad ((->) t)
    In the definition of `it': it = (Data.Map.lookup "+" a) 1 2

... не очень полезно для меня.

Есть предложения?Спасибо!

Ответы [ 3 ]

7 голосов
/ 06 января 2011

поиск имеет тип lookup :: Ord k => k -> Map k a -> Maybe a.Результат обернут в «Возможно», чтобы указать, что ключ может отсутствовать на карте.

Вот способ сделать это, который будет работать:

runOp :: String -> a -> a -> b
runOp key x y = case lookup key ops of
                  Just op -> op x y
                  Nothing -> error ("Couldn't find operator: " ++ key)

Это снизится, еслиключа нету.Вы также можете вернуть результат Either или Maybe из runOp, чтобы учесть вероятность того, что ключ отсутствует, но это зависит от вас.

Может быть определено следующим образом:

data Maybe a = Just a | Nothing

то есть он содержит либо значение результата, либо пустое значение.Как экзистенциальный философ, Хаскелл заставляет вас признать возможность Nothing.

4 голосов
/ 06 января 2011

Прежде всего, ошибка, которую вы показали, не вызвана кодом, который вы показали.Ваш код вызывает следующую ошибку (в ghc):

Couldn't match expected type `t1 -> t2 -> t'
against inferred type `Data.Maybe.Maybe

Эта ошибка вызвана тем, что lookup возвращает Maybe.Поэтому вам нужно сначала развернуть Maybe.

2 голосов
/ 06 января 2011
import Control.Applicative

ops :: (Fractional a) => Map.Map String (a -> a -> a)
ops = Map.fromList [("+", (+)),
                    ("-", flip (-)),
                    ("*", (*)),
                    ("/", flip (/))]

apply :: (Fractional a) => String -> a -> a -> Maybe a
apply op x y = Map.lookup op ops <*> y <*> x

Поскольку lookup возвращает Maybe a (ну, в данном случае Maybe (a -> a -> a)), невозможно напрямую применить его к a.Мы можем использовать <*>, чтобы вытащить LHS из мотылька, применить его к RHS и ввести его обратно в монаду.(Или сделайте это вручную, как Билл.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...