Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - How to use a function that returns 'Maybe Int' as an argument to another function?

Tags:

haskell

When I have the two functions:

a)

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? i.e How do I let function b accept a 'Maybe Int' in place of an 'Int'?

At the minute when I try

takeOne (three 3)

I get the error:

ERROR - Type error in application
*** Expression     : takeThree (three 3)
*** Term           : three 3
*** Type           : Maybe Int
*** Does not match : Int

Thanks.

like image 387
Charles Del Lar Avatar asked Oct 15 '14 16:10

Charles Del Lar


1 Answers

You've got a few options, but I'd say the easiest 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 the function maybe, which takes a default value, a function to apply to any value inside the Just, and then the Maybe a to apply this to. 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 give a default value is to use the function fromMaybe from Data.Maybe:

> import Data.Maybe
> fromMaybe 0 $ three 3
3
> fromMaybe 0 $ three 2
0

In Haskell, there is a typeclass called Functor defined as

class Functor f where
    fmap :: (a -> b) -> f a -> f b

There are many, many types that are instances of Functor. In fact, all parametrized data structures are Functors, as are all Applicatives and Monads. The easiest mental model of a Functor is that it's just a fancy name for a container. For lists, fmap = map, for example. All it does is map a function over the elements inside a container.

Some more examples are:

> 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 are Functors! Here fmap = (.), it's just normal function composition:

> let lengthPlusOne = fmap (+1) length
> lengthPlusOne "Hello"
6
like image 70
bheklilr Avatar answered Sep 28 '22 15:09

bheklilr