Harry Payne
Harry Payne

Reputation: 63

Haskell Maybe not working on higher order function

I'm new to Haskell and I'm trying to make a function that takes in a string which is an operator and maybe returns a function. So that hopefully I could run the following command:

operationOn1 "+" 5 

Which I hope would return 6. This is my code:

add1 :: Integer -> Integer
add1 x = x + 1

sub1 :: Integer -> Integer
sub1 x = x - 1

operationOn1 :: String -> Maybe(Integer -> Integer)
operationOn1 "+" = Just add1
operationOn1 "-" = Just sub1
operationOn1 _ = Nothing

I'm too new to this to know what to google to find any help, all of the tutorials I can find about the maybe keyword don't go into higher order functions so I'm not sure what I am doing wrong.

Upvotes: 1

Views: 230

Answers (2)

talex
talex

Reputation: 20446

You can introduce your own helper function

($>) :: Maybe (a -> b) -> a -> Maybe b
($>) Nothing _ = Nothing
($>) (Just f) a = Just $ f a

and use it operationOn1 "+" $> 5

Upvotes: 1

AJF
AJF

Reputation: 11913

You can't immediately use something of type Maybe (Integer -> Integer) like you would use something of type Integer -> Integer. In other words, this line doesn't work:

λ operationOn1 "+" 5
--^^^^^^^^^^^^^^^^ This part is of type `Maybe (Integer -> Integer)`.
--                 ^ Using it in this way is incorrect,
--                   since it is not of type `Integer -> Integer`.

In fact, if you read the error message, it tells you exactly this. Always read the error message:

error:
    • Couldn't match expected type ‘Integer -> t’
                  with actual type ‘Maybe (Integer -> Integer)’
    • The function ‘operationOn1’ is applied to two arguments,
      but its type ‘String -> Maybe (Integer -> Integer)’ has only one
      In the expression: operationOn1 "+" 5
      In an equation for ‘it’: it = operationOn1 "+" 5

So, we need to deal with the Maybe ... 'wrapper' that is around the function we want to use.

There is an inbuilt function specifically to deal with this kind of situation, namely (<*>) :: (Applicative f) => f (a -> b) -> f a -> f b, like so:

λ operationOn1 "+" <*> Just 5
Just 6
λ operationOn1 "-" <*> Just 4
Just 3
λ operationOn1 "what?" <*> Just 3
Nothing

If you don't know what an applicative functor is, I'd highly recommend reading the LYAH chapter on functors, applicative functors, and monoids.

Upvotes: 7

Related Questions