Search code examples
haskelloption-type

How do I use the "Maybe" data type in a math expression in Haskell?


MRE:

foo :: (Eq a) => a -> [a] -> Maybe Int
foo _ [] = Nothing
foo n (m:ms)
    | -- some conditional statements that return Just <number here>
    | otherwise = 3 + (foo n ms)

Error:

Could not deduce (Num (Maybe Int)) arising from a use of ‘+’
      from the context: Eq a
        bound by the type signature for:
                   foo :: forall a. Eq a => a -> [a] -> Maybe Int
        at functions.hs:22:1-40
In the expression: 3 + (foo n ms)

What works:

otherwise = fmap (+3) (foo n ms)

Is there any way to do this without fmap?

PS: The only constraint on a is Eq has to hold.


Solution

  • The problem is that 3 is Int but (foo n ms) is Maybe Int, and you cannot add them.

    You can pattern match on the result of foo n ms explicitly if you don't want to fmap over Maybe Int.

    otherwise = case foo n ms of
                  Just x -> Just (3 + x)
                  Nothing -> Nothing
    

    It's also an option to use a Monad instance of Maybe, but it's kind of a redundant version of fmap (+3) (foo n ms).

    otherwise = do
      x <- foo n ms
      pure (3 + x)
    

    Yet another option would be lifting (+) to Maybe Int -> Maybe Int -> Maybe Int with liftA2, but again, it's kind of another redundant version.

    otherwise = liftA2 (+) (Just 3) (foo n ms)