Applicatives
haskell2-1's fmap handles a plain function applied to one wrapped value. This chapter handles the next real gap: what happens when the function itself is wrapped too.
The Problem Functor Can't Solve
fmap requires a plain, unwrapped a -> b. It genuinely cannot express applying Just (+3) to Just 5 — the function is wrapped too, and nothing in fmap's own type signature has anywhere to put a wrapped function.
The Applicative Typeclass & <*>
Applicative requires Functor as a superclass — a real hierarchy: every Applicative is automatically a Functor too. <*> applies a wrapped function to a wrapped value, exactly the case fmap couldn't handle.
pure — Wrapping a Plain Value
pure lifts an ordinary value into the applicative context using the minimal, default wrapping — genuinely useful for starting a chain of applicative operations from a plain, unwrapped value.
Combining Independent Computations
Here's the real, practical use case: combining two separately-wrapped values with an ordinary multi-argument function. java2-1's/csharp2-1's own generics have no equivalent mechanism for this at all — combining two independently-wrapped values with a plain function requires manual unwrapping in both, since neither language's generics carry this kind of combining operation as part of the type itself.
A Real Practical Example — Validating Multiple Fields
A genuinely realistic, common Haskell idiom — building a record from several independently-validated fields, where the whole construction fails if any single field does.
The Bridge to Monad
Stated explicitly, not just implied: Applicative combines independent computations — neither can depend on the other's actual result, only on whether each independently succeeded or failed. Chapter 3's own Monad is exactly what's needed once a later computation needs to depend on an earlier one's real, concrete value. Applicative isn't a lesser version of Monad — it's a genuinely useful, distinct stepping stone for the many real cases where independence is all that's actually needed.
| Typeclass | Function is wrapped? | Can later steps depend on earlier results? |
|---|---|---|
| Functor (haskell2-1) | no — plain a -> b | n/a — only one value involved |
| Applicative | yes — f (a -> b) | no — combines independently |
| Monad (Chapter 3) | n/a — uses >>= instead | yes — the whole point |
Coding Challenges
Use <*> to apply Just (*2) to Just 10, and separately apply Nothing (of the correct function type) to Just 10, printing both results.
📄 View solutionWrite a three-argument record constructor and combine three independently-Maybe-wrapped fields into one Maybe of the record using <$> and <*> chained together, testing both a fully-successful case and a case where one field is Nothing.
📄 View solutionWrite a short comment giving a concrete, realistic example of a task that CANNOT be expressed using Applicative alone (where a later step genuinely needs an earlier step's actual value), explaining exactly why <*> falls short for it.
📄 View solutionChapter 2 Quick Reference
- Applicative solves what Functor can't: applying a WRAPPED function to a wrapped value, via <*>
- Applicative requires Functor as a superclass — every Applicative is automatically a Functor
- pure lifts a plain value into the applicative context with minimal wrapping
- f <$> a <*> b combines independently-wrapped values with an ordinary function — no equivalent in java2-1's/csharp2-1's own generics
- Applicative combines INDEPENDENT computations only — no later step can depend on an earlier step's actual result
- Next chapter: Monads — the track's central payoff, where dependent computations finally become possible