Apply me both lists
Tags: functional, haskell
Published: 2020-01-13 22:22:17

---
title: Apply me both lists
published: true
description: A use case for the Applicative instance of Lists
tags: functional,haskell
series: 100 Days Of FP

cover_image: https://thepracticaldev.s3.amazonaws.com/i/jxrxbwhhiu3nuynzwblp.jpg
---

As we saw in the previous one, Applicative allows to apply _n-ary_ functions in a context. The context might be a parser, values that are potentially be errors, a list or a tree, optional values, IO actions, etc.

In my short learning experience so far, I've used it in practice for two things mostly.

Constructing values with data constructors that take several values. For example, those values would come from sequential parsers when working with parser combinators (like [Parsec](https://hackage.haskell.org/package/parsec)).

```hs
data User = User String String Int

-- "John Doe 26" -> User "John" "Doe" 26
parseUser :: Parser User
parseUser =
  User <$> (parseWord <* whitespace)
       <*> (parseWord <* whitespace)
       <*> parseAge

parseWord :: Parser String
parseAge :: Parser Int

whitespace :: Parser () -- consumes as much whitespace as possible

-- Defined in Control.Applicative
(<*) :: Applicative f => f a -> f b -> f a
```

`(<*)` is the lifted version of `const`, [here](https://dev.to/gillchristian/lifting-const-1a3l) is something I wrote about that. As we can guess from the signature, in this case it applies both parses (ie. both consume input) but returns the first one, ignoring the second.

And the other use case, applying _n-ary_ functions to values that might not be there. In other words, when the context is Either or Maybe.

```hs
add <$> (Just 1) <*> (Just 2) -- Just 3
add <$> Nothing  <*> (Just 2) -- Nothing
add <$> (Just 1) <*> Nothing  -- Nothing
add <$> Nothing  <*> Nothing  -- Nothing

add <$> (Right 1)      <*> (Right 2)      -- Right 3
add <$> (Left "err 1") <*> (Right 2)      -- Left "err 1"
add <$> (Right 1)      <*> (Left "err 2") -- Left "err 2"
add <$> (Left "err 1") <*> (Left "err 2") -- Left "err 1"
```

### Lists

Until last week I hadn't found a use case for Applicative when working with lists. I knew how it works but never had ~~an excuse~~ a reason to use it.

Let's take a look at the instance and some examples first.

```hs
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

-- With [] applied to f (using TypeApplications extension)
(<*>) @[] :: [a -> b] -> [a] -> [b]

(+) <$> [1, 2, 3] <*> [1, 2, 3]
-- [2,3,4,3,4,5,4,5,6]

(,) <$> [1, 2, 3] <*> [1, 2, 3]
-- [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

[(++ "!"), (++ "?")] <*> ["Hola", "Mundo"]
-- ["Hola!","Mundo!","Hola?","Mundo?"]
```

As we can see, it takes a list of functions (`[a -> b]`) and a list values (`[a]`) and applies all the functions from the first list to all the values from the second one, this results in a larger list (duh!). If list sizes are `n` and `m`, respectively, the size of the returned list is `n * m`.

That's not a use case that I find very often. Most of the time I have one function (`a -> b`) that I want to apply to a list of values (`[a]`). That's Functor's `fmap` (as well as `(<$>)`). Or I have a list of functions to apply to a single value. For example, it could be list of predicates and I want to check if all or some are `True` for a particular value.

```hs
allPass :: [a -> Bool] -> a -> Bool

anyPass :: [a -> Bool] -> a -> Bool
```

By the way, there are similar functions [defined in Base](https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html#v:and):

```hs
and :: [Bool] -> Bool -- True when all are True

or :: [Bool] -> Bool  -- True when at least one is True
```

In the case of lists, what applicative does is apply all the functions too all the values.

Last week, playing around on small side project, [till](https://github.com/gillchristian/till). I was trying to add the option to match several patterns against the same value and I found a use case for List's Applicative.

There's a `match` function that checks if a pattern matches a single line of the output.

```hs
match :: Pattern -> Line -> Bool
```

The output consists of a list of lines. When working with a single pattern, the solution is easy. Use [any](https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:any) (from Base).

```hs
any :: Foldable t => (a -> Bool) -> t a -> Bool

any @[] :: (a -> Bool) -> [a] -> Bool

matchPattern :: Pattern -> [Line] -> Bool
matchPattern p lns = any (match p) lns
```

What about matching several patterns against the output?

```hs
matchAll :: [Pattern] -> [Line] -> Bool
matchAll ps lns = undefined -- ???
```

Applicative to the rescue :tada:

```hs
matchAll :: [Pattern] -> [Line] -> Bool
matchAll ps lns = or (match <$> ps <*> lns)
```

Let's dissect that :mag:

```hs
-- So we don't forget ;)
(<$>) @[] :: (a -> b) -> [a] -> [b]
   
(<*>) @[] :: [a -> b] -> [a] -> [b]

-- ^ notice the difference between <$> & <*> ;)

or :: [Bool] -> Bool

match :: Pattern -> Line -> Bool

-- the input
ps :: [Pattern]

lns :: [Line]

-- mapping first to partially apply the patterns to match
match <$> ps :: [Line -> Bool]

-- applying the lines
match <$> ps <*> lns :: [Bool]

-- reducing that to get our result
or (match <$> ps <*> lns) :: Bool
```

I like how elegant this looks thanks to Functor and Applicative 🎩

_NOTE_: I'm sure there are other ways to solve the problem, with better performance. Although in my use case both lists _should_ be relatively short, usually between one and three patterns and around 100 or probably less lines of output.

Happy and safe coding :unicorn: