Search for the name of a special display function

I'm new to Haskell and I'm looking for a function name (or generally a concept name) that acts as such:

The function takes two arguments:
1. A list of elements [T]
2. A function that takes T and returns Maybe U.

The output of the function is as follows:
If all the elements in the list match some U, return Some [U].
Otherwise, return None.

i.e. if any of the displayed values ​​are NULL then return zero, otherwise just return the displayed values.

+3


source to share


5 answers


Haskell report calls it sequence . map f

, also called mapM f

. Currently, you can call it traverse f

(GHC 7.10+).

Map and sequence

Let's think about the type of your function:

withList :: (a -> Maybe b) -> [a] -> Maybe [b]

      

A canonical function to map a list to another:, map

so we can use that as a starting point:

withListNotYet :: (a -> Maybe b) -> [a] -> [Maybe b]
withListNotYet f xs = map f xs

      

We now have a list Maybe b

, but we want to get the Maybe

outside. This is essentially what sequence

does:

sequence :: Monad m => [m a] -> m [a]
sequence []     = return []
sequence (x:xs) = do
  y  <- x
  ys <- sequence xs
  return (y : ys)

      

Since it Maybe

is an instance Monad

, we can use sequence

after withListNotYet

and complete our implementation for withList

:

withList f xs = sequence (map f xs)

      

Since this is a common operation, it has a name mapM

::



withList f xs = mapM f xs
-- or
withList = mapM

      

Traversable

During the "proposal to change bridges" , the type was mapM

changed from

mapM     :: Monad m                        => (a -> m b) -> [a] -> m [b]

      

to

mapM     :: (Monad m, Traversable t)       => (a -> m b) -> t a -> m (t b)

      

At that time, there was already a similar function called traverse

:

traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

      

As you can see, the type signature is very similar. The same version of GHC that changed the type mapM

also made it a Applicative

base class Monad

, see Functor-Applicative-Monad-Proposal . So nowadays, you can usually use traverse

or mapM

. The first is a younger, more general version, and the last is an older, historical version.

And if you look at the class Traversable

, you will notice that mapM = traverse

the default.

+7


source


This traverse

, defined in the class Traversable

:

traverse :: Traversable t, Applicative f => (a -> f b) -> t a -> f (t b) 

      



your example t

has a list and f

there is Maybe

eg.

traverse (\x -> if x < 5 then Just x else Nothing) [1,2,3]
> Just [1,2,3]

traverse (\x -> if x < 5 then Just x else Nothing) [1,2,3, 9]
> Nothing

      

+12


source


The function is called traverse

, from Data.Traversable

.

The type may surprise you at first because it is rather abstract:

traverse :: (Applicative f,Traversable t) => (a -> f b) -> t a -> f (t b)


Applicative

and Traversable

- two interfaces (type classes in Haskell terms).

  • Theses Applicative

    on the effects that we want to perform. In your case it is failing ( Maybe

    ), but it can also fail ( Either

    ), input / ouput ( IO

    ), concurrent I / O ( Concurrently

    ) and many others.

  • Abstracts Traversable

    by type of container. In your case, it's a list ( []

    ). But other containers also Traversable

    : final containers, which have a shape that is independent of their own values. Trees and Maps are examples. ( Presets are not an example, because their "shape" depends on their values: changing all items to the same value will reduce the size of the set.)

Traversable

is an interface for containers that support "internal iteration". These are mostly forEach

other languages. But it also provides you with a results container of the same shape as the original, which contains the converted values.

If you don't need the transformed container, the associated function traverse_

discards the result and is only executed for effects.

Function mapM

is a synonym traverse

that exists for historical reasons.

+5


source


These are all really good answers. I just want to add to the board that you can find this information faster with hoogle. If you know what you are looking for, enough that you can create a type signature for your desired expression, hoogle will look for it. He's smart enough to understand type variables, etc. (I.e. It doesn't matter if you write T and U as you do, or and b as you do in Haskell).

Taking your example verbatim, [T] -> (T -> Maybe U) -> Maybe [U]

you will find among others traverse and mapM, both of which have been mentioned by other peers. Happy hoogling!

+2


source


While this Data.Traverable.traverse

appears to be the correct answer, you can also implement similar functionality yourself.

isJust :: Maybe a -> Bool
isJust (Just _) = True
isJust _        = False

withList :: (a -> Maybe b) -> [a] -> Maybe [b]
withList f xs | all isJust js = Just (map (\(Just x) -> x) js)
              | otherwise     = Nothing
              where js = map f xs

*Main> withList (\xs -> if all (<10) xs then (Just (sum xs)) else Nothing) [[1,2,3],[4,5,6],[7,8,9]] 
Just [6,15,24]
*Main> withList (\xs -> if all (<9) xs then (Just (sum xs)) else Nothing) [[1,2,3],[4,5,6],[7,8,9]]
Nothing

      

+1


source







All Articles