MrD
MrD

Reputation: 5086

Haskell checking return type of function from another function

I have a Haskell code that has two functions:

The first function:

functionA :: [Int] -> Maybe Int

The second one:

functionB :: Int -> Maybe Int

What I want to do is to recurse on every element of [Int] and feed it into functionB. If function B returns an Int, then move to the next element, if it returns Nothing, then functionA returns nothing too.

Any idea how best to do this?

Thanks :)

Upvotes: 1

Views: 566

Answers (3)

viorior
viorior

Reputation: 1803

J. Abrahamson answered right, but he named the result function unusually and it confused you.

Let we have ints:

ints :: [a]

functionA :: [a] -> Maybe a

functionB :: a -> Maybe a

So we wish to get map functionB:

functionC :: a -> Maybe [a]
functionC ints = mapM functionB ints

but functionC has result type Maybe [a], not [a], so we use fmap

result :: [a] -> Maybe a
result ints = join $ fmap functionA $ functionC ints

And we also use join to get rid of Maybe (Maybe a) result

Or let's write in one line:

result :: [a] -> Maybe a
result = join . fmap functionA . mapM functionB

UPDATED

But in this solution always calculates all ints. If we wish to stop calculating, we need to have mapIfAllJust function, like this:

result :: [a] -> Maybe a
result = join . fmap functionA . sequence . mapIfAllJust functionB

mapIfAllJust :: (a -> Maybe b) -> [a] -> [Maybe b]
mapIfAllJust _ []     = []
mapIfAllJust f (x:xs) = go f (f x) [] xs
where
    go _ Nothing _    _         = [Nothing]
    go _ pr      used []        = pr : used
    go f pr      used (nxt:rst) = go f (f nxt) (pr : used) rst    

Upvotes: 0

Ankur
Ankur

Reputation: 33637

Your question has few things that are not clear hence I am making few assumptions. functionA is like a fold as it transform a [Int] to Maybe Int but before folding the ints it calls functionB to transform each integer into a Maybe Int where Nothing result indicate a failure in transformation and which leads to failure of the functionA and making it return Nothing.

import Control.Applicative

functionA :: [Int] -> Maybe Int
functionA nums = foldl (\x y -> (+) <$> x <*> y) (Just 0) $ map functionB nums

functionB :: Int -> Maybe Int
functionB 2 = Nothing
functionB x = Just (x+x)

In the example above, the + is used in the fold operation and functionB fails on number 2

Upvotes: 1

J. Abrahamson
J. Abrahamson

Reputation: 74354

You can use sequence to take [Maybe Int] to Maybe [Int]

functionA ints = sequence (map functionB ints)

Generally this combination of sequence and map is called mapM.

functionA ints = mapM functionB ints

Upvotes: 3

Related Questions