Home > Enterprise >  Haskell Maybe adder without Arguments
Haskell Maybe adder without Arguments

Time:11-19

I am wondering if it is possible to wirte the Function

add :: Maybe Int -> Maybe Int
add Just x = Just (x 1)
add Nothing = Nothing

without the x. Similar to

f = Just.( 1)

However

add Just = Just.( 1)

throws an error: Equations for 'add' have different numbers of arguments. Can someone please explain me why this does not work?

CodePudding user response:

You need to pattern match somewhere - there's no way to "get the value out" without doing so. You can use some unsafe function, like fromJust, but

  • it's unsafe - doing a case and pattern matching is better
  • it's still doing pattern matching in it, so you're not really avoiding doing it.

The "proper modular" way to do this, would be to write this common pattern as a higher-order function, so that you can reuse it:

  • in the Nothing case, you return Nothing
  • in the Just case, you return Just of some function applied to the arg inside

Taking into account the two things above, we reach the following

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

which you can now use to write your desired function:

add :: Maybe Int -> Maybe Int
add x = maybeMap ( 1) x
-- or we can eta reduce it - taking an argument and calling a function with it is the same as just returning the function directly
add = maybeMap ( 1)

This function is traditionally called map, because you're mapping "the values inside a container" to something else.

This is something that you very often need to do for different "containers" (and some other kinds of things), so we have a type class for it in the standard library (base), named after some theoretical things:

class Functor f where
  fmap :: (a -> b) -> f a -> f b
instance Functor [] where
  fmap = map
instance Functor Maybe where
  fmap = maybeMap

Additionally, the error you're seeing is something else entirely. In Haskell, when writing a function definition, your different cases are not allowed to have different numbers of arguments taken:

-- not allowed, since in the first case you've taken two args,
-- but in the second you've only taken one.
bla :: Integer -> Integer -> Integer
bla 0 y = 42
bla x = id

-- this is fine, in both cases we have two arguments
bla :: Integer -> Integer -> Integer
bla 0 y = 42
bla x y = y

CodePudding user response:

The first parameter is a Maybe Int, hence it is not sufficient to only specify the Just data constructor: this data constructor has one parameter x. You thus should use (Just x), (Just _) or Just {} to match where the last two ignore the value wrapped in the Just data constructor. But in that case you thus can not access that value.

Your function however is a special case of an fmap :: Functor f => (a -> b) -> f a -> f b with f ~ Maybe and as mapping function ( 1). Indeed, the Functor instance of Maybe is implemented as [src]:

instance  Functor Maybe  where
    fmap _ Nothing       = Nothing
    fmap f (Just a)      = Just (f a)

You thus can implement add as:

add :: Maybe Int -> Maybe Int
add = fmap (1 )
  • Related