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?
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
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:
Nothing case, you return NothingJust case, you return Just of some function applied to the arg insideTaking 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
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+)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With