Generalizes [[Functor#map|map]] to [[Functions|functions]] with 2+ arguments; lifting functions `a -> b -> c` to `f a -> f b -> f c` ```haskell class Functor f <= Apply f where apply :: forall a b. f (a -> b) -> f a -> f b infixl apply as <*> ``` > [!tip] > Apply often replaces the pattern of "building towards a final result" > > Consider a function that [[Tuple|tuple]]s together its arguments > ```haskell > mk3Tuple a b c = a /\ b /\ c > ``` > > A common situation is wanting to build something like this 3-tuple from some components that are trapped in a context like [[Maybe]] or [[Either]], and we want to say "when all these things are ok, build it"; this is exactly what Apply lets us do: > > ```haskell > maybeMk3Tuple :: Maybe a -> Maybe b -> Maybe c -> Maybe (a /\ b /\ c) > maybeMk3Tuple ma mb mc = Just mk3Tuple <*> ma <*> mb <*> mc > > maybeMk3Tuple (Just 1) (Just 2) (Just 3) > -- Just (1 /\ 2 /\ 3) > > maybeMk3Tuple (Just "a") (Just 3) (Nothing) > -- Nothing > > maybeMk3Tuple Nothing Nothing Nothing > -- Nothing > ``` > [!tip] > Obscure but occasionally usefully, Apply in collections lets us apply multiple functions to each element: > ```haskell > [(_ * 10), (_ * 20)] <*> [1, 2, 3] > -- [10, 20, 20, 40, 30, 60] > > [identity, const ", "] <*> ["a", "b", "c"] > -- ["a", ",", "b", ",", "c", ","] > ``` ### Examples lift `(a + b) / c` to [[Maybe]] ```haskell f :: Number -> Number -> Number f a b c = (a + b) / c mf :: Maybe Number -> Maybe Number -> Maybe Number mf ma mb mc = pure f <*> ma <*> mb <*> mc ``` Build up a `Person` [[Record|record]] from Maybe fields; short-circuiting to `Nothing` if any fields are `Nothing` ```haskell type PartialPerson = { name :: Maybe String , email :: Maybe String , password :: Maybe String } type Person = { name :: String , email :: String , password :: String } person :: PartialPerson -> Person person { name: name' , email: email' , password: password' } = let buildPerson name email password = {name, email, password} in Just buildPerson <*> name' <*> email' <*> password' ```