Haskell - How to use a function that returns "Maybe Int" as an argument to another function?
When I have two functions:
and)
three :: Int -> Maybe Int
three a
| a == 3 = Just 3
| otherwise = Nothing
b)
takeOne :: Int -> Int
takeOne a = (a - 1)
how do I call function a as a parameter to function b? ie How do I let function b accept "Maybe Int" instead of "Int"?
The moment I try
takeOne (three 3)
I am getting the error:
ERROR - Type error in application
*** Expression : takeThree (three 3)
*** Term : three 3
*** Type : Maybe Int
*** Does not match : Int
Thank.
source to share
You have several options, but I would say that the simplest is fmap
:
fmap :: Functor f => (a -> b) -> f a -> f b
Example:
> fmap takeOne $ three 3
Just 2
> fmap takeOne $ three 2
Nothing
Another option would be to use a function maybe
that takes a default, a function that is applied to whatever value inside Just
, and then to Maybe a
apply that parameter. An example should make it clear
> maybe 0 takeOne $ three 3
2
> maybe 0 takeOne $ three 2
0
Another alternative, if you just want to provide a default value, is to use a function fromMaybe
from Data.Maybe
:
> import Data.Maybe
> fromMaybe 0 $ three 3
3
> fromMaybe 0 $ three 2
0
In Haskell, there is a class called Functor
, defined as
class Functor f where
fmap :: (a -> b) -> f a -> f b
There are many different types that are instances Functor
. In fact, all parameterized data structure Functor
s, as well as all Applicative
and Monad
s. The lightest mental model Functor
is that this is just a fancy name for a container. For example, for lists fmap = map
. All it does is render the function over the elements inside the container.
Some more examples:
> fmap (+1) (Left "error")
Left "error"
> fmap (+1) (Right 1)
Right 2
> x <- fmap (++", world") getLine
Hello
> x
Hello, world
> fmap (+1) [1..5]
[2,3,4,5,6]
> fmap (+1) ("fst", 2)
("fst", 3)
Even functions Functor
s! Here fmap = (.)
, this is just the normal composition of the function:
> let lengthPlusOne = fmap (+1) length
> lengthPlusOne "Hello"
6
source to share
Another option, of course, is to write your own.
data IAcceptedAMaybeInt = GotAnswer Int | NothingAtTheMoment deriving Show
pleaseAcceptAMaybeInt f g a = case g a of
Just b -> GotAnswer (f b)
otherwise -> NothingAtTheMoment
Output:
*Main> pleaseAcceptAMaybeInt takeOne three 3
GotAnswer 2
*Main> pleaseAcceptAMaybeInt takeOne three 2
NothingAtTheMoment
source to share