开发者

Map that associates operators with lambda functions

开发者 https://www.devze.com 2023-02-03 00:56 出处:网络
I have a Haskell Map, containing strings as keys and some lambda functions as items . Eg.: -- List of supported Operators -> mapping with functions

I have a Haskell Map, containing strings as keys and some lambda functions as items . Eg.:

-- List of supported Operators -> mapping with functions
开发者_如何学Cops = Map.fromList [("+", \x y -> x + y),
                    ("-", \x y -> y - x),
                    ("*", \x y -> x * y),
                    ("/", \x y -> y / x)]

I want to write a function that takes as input:

  • A string representing an operator ["+", "-", "*", "/"]
  • Two numbers

Based on the operator and the ops map, the function will evaluate the sum/subtraction/etc. of the two numbers .

I've tried something like:

(Map.lookup "+" a) 1 2

But it's not working .

The error is:

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

... not very helpful for me.

Any suggestions ? Thank you !


lookup is of type lookup :: Ord k => k -> Map k a -> Maybe a. The result is wrapped in a Maybe to indicate that the key may not be present in the map.

Here's a way to do it that will work:

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)

This will bottom out if the key is not present. You could also return an Either or Maybe result from runOp to accommodate the possibility that the key isn't present, but that's up to you.

Maybe is defined as follows:

data Maybe a = Just a | Nothing

that is, it either holds a result value or an empty value. Like an existential philosopher, Haskell forces you to acknowledge the possibility of Nothing.


First of all the error you showed is not caused by the code you showed. Your code causes the following error (in ghc):

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

That error is caused by the fact that lookup returns a Maybe. So you need to unwrap the Maybe first.


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

Because lookup returns a Maybe a (well, Maybe (a -> a -> a) in this case), there is no way to directly apply it to an a. We can use <*> to pull the LHS out of the mote, apply it to the RHS, and inject it back into the monad. (Or do it manually like Bill.)

0

精彩评论

暂无评论...
验证码 换一张
取 消