Haskell: Return an operator (like +, -, >, etc) from a function and perform the operation

Viewed 99

I have two variables,

let x = 3
let y = 4

And I have a bunch of operators in the form of Plus, Minus, Lt, Gt, Gte, etc.

data Operator = Plus | Minus | Divide | Gt | Lt ....

I am trying to write a function that takes in an Operator type and returns the actual operator. Like:

returnOperator :: Operator -> (Int->Int->a)
returnOperator op = case op of
                         Plus -> (+)
                         Minus -> (-)
                         Gt -> (>) 
                         ...etc

So I can do:

let output_op = returnOperator (Plus)
let z = x `output_op` y 
z = 7

As an example. However, my returnOperator function as written gives an error:

Couldn't match type ‘a’ with ‘Int’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          returnOp :: forall a. Operator -> Int -> Int -> a

Any suggestions on how to fix this issue?

1 Answers

One way is to separate your operators by type.

data BoolOperator = Gt | Lt | ...
data IntOperator = Plus | Minus | Divide | ...

boolOp :: BoolOperator -> Int -> Int -> Bool
intOp :: IntOperator -> Int -> Int -> Int

A more advanced way, of questionable marginal utility, is to use a GADT.

data Operator a where
    Plus :: Operator Int
    Gt :: Operator Bool

returnOperator :: Operator a -> Int -> Int -> a
returnOperator Plus = (+)
returnOperator Gt = (<)

Note that this doesn't buy you as much as you might think at first; in particular, any homogeneous data structure like lists or Maps will not be able to store both Plus and Gt, because they have different types.

Related