Tutorial :Applying a function that may fail to all values in a list



Question:

I want to apply a function f to a list of values, however function f might randomly fail (it is in effect making a call out to a service in the cloud).

I thought I'd want to use something like map, but I want to apply the function to all elements in the list and afterwards, I want to know which ones failed and which were successful.

Currently I am wrapping the response objects of the function f with an error pair which I could then effectively unzip afterwards

i.e. something like

g : (a->b) -> a -> [ b, errorBoolean]

f : a-> b

and then to run the code ... map g (xs)

Is there a better way to do this? The other alternative approach was to iterate over the values in the array and then return a pair of arrays, one which listed the successful values and one which listed the failures. To me, this seems to be something that ought to be fairly common. Alternatively I could return some special value. What's the best practice in dealing with this??


Solution:1

If f is making a call out to the cloud, than f is undoubtedly using some monad, probably the IO monad or a monad derived from the IO monad. There are monadic versions of map. Here is what you would typically do, as a first attempt:

f :: A -> IO B -- defined elsewhere  g :: [A] -> IO [B]  g xs = mapM f xs  -- or, in points-free style:  g = mapM f  

This has the (possibly) undesirable property that g will fail, returning no values, if any call to f fails. We fix that by making it so f returns either an answer or an error message.

type Error = String  f :: A -> IO (Either Error B)  g :: [A] -> IO [Either Error B]  g = mapM f  

If you want all of the errors to be returned together, and all of the successes clumped together, you can use the lefts and rights functions from Data.Either.

h :: [A] -> IO ([B], [Error])  h xs = do ys <- g xs            return (rights ys, lefts ys)  

If you don't need the error messages, just use Maybe B instead of Either Error B.

The Either data type is the most common way to represent a value which can either result in an error or a correct value. Errors use the Left constructor, correct values use the Right constructor. As a bonus, "right" also means "correct" in English, but the reason that the correct value uses the Right constructor is actually deeper (because this means we can create a functor out of the Either type which modifies correct results, which is not possible over the Left constructor).


Solution:2

You could write your g to return a Maybe monad:

f: a -> b  g: (a -> b) -> a -> Maybe b  

If f fails, g returns Nothing, otherwise it returns Just (f x).


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »