# Applicative: Combining Independent Effects — Haskell

Source: https://www.geekswithgeeks.com/en/haskell/a-applicative

> Combine several values in a context with <*>, liftA2 and traverse.

## Applying functions of several arguments

`fmap` handles functions of one argument. To combine **several** values that are each in a context, such as two `Maybe` values or two `IO` actions, use **`Applicative`**. It adds **`pure :: a -> f a`** (put a plain value into the context) and **`<*>`** (apply a function in a context to a value in a context). The idiom `f <$> x <*> y <*> z` applies a three-argument function to three contextual values: `Signup <$> validName n <*> validEmail e <*> validAge a`. **`liftA2 f x y`** is equivalent to `f <$> x <*> y`. With `Maybe`, the result is `Nothing` if any input is `Nothing`; with lists, `<*>` produces all combinations; with `IO`, effects run left to right. The key difference from `Monad`: in an applicative expression, the **effects are independent** of each other's results, which allows parallel or analysable effects, and `Validation`-style types (such as from the `validation` package) can **accumulate all errors** instead of stopping at the first. **`traverse`** and **`sequenceA`** use `Applicative` to run an effectful function over every element of a structure: `traverse readMaybe ["1", "2"]` is `Just [1, 2]`.

## Applicative style

Combining independent results and traversing lists.

```haskell
import Text.Read (readMaybe)
import Control.Applicative (liftA2)

data Dimensions = Dimensions { widthCm :: Int, heightCm :: Int, depthCm :: Int }
  deriving Show

parseDims :: String -> String -> String -> Maybe Dimensions
parseDims w h d = Dimensions <$> readMaybe w <*> readMaybe h <*> readMaybe d

volumetricWeightGrams :: Dimensions -> Int
volumetricWeightGrams (Dimensions w h d) = (w * h * d) `div` 5     -- (cm^3 / 5000) kg, in grams

main :: IO ()
main = do
  print (parseDims "30" "20" "10")                 -- Just (Dimensions 30 20 10)
  print (parseDims "30" "twenty" "10")             -- Nothing
  print (volumetricWeightGrams <$> parseDims "30" "20" "10")   -- Just 1200
  print (liftA2 (+) (Just 3) (Just (4 :: Int)))    -- Just 7
  print ((,) <$> [1, 2 :: Int] <*> "ab")           -- [(1,'a'),(1,'b'),(2,'a'),(2,'b')]
  print (traverse readMaybe ["1", "2", "3"] :: Maybe [Int])   -- Just [1,2,3]
  print (sequenceA [Just 1, Nothing, Just (3 :: Int)])        -- Nothing
  greeting <- (++) <$> pure "Hello, " <*> getLine             -- effects run left to right
  putStrLn greeting
```

## Reach for Applicative before Monad

If later steps do not depend on earlier results, applicative style (`f <$> a <*> b`) states that independence clearly and works with more types, including error-accumulating validation.

**Quiz:** What does `f <$> Just 1 <*> Nothing` evaluate to (for a two-argument f)?

- [ ] Just (f 1)
- [x] Nothing
- [ ] An exception
- [ ] Just 1

*Answer:* Nothing. If any applicative input is Nothing, the result is Nothing.
