Home Posts Post Search Tag Search

Advanced Functional Elixir - 09 - Act on It
Published on: 2026-04-26 Tags: elixir, Blog, Advanced Functional Programming, FunPark, Act on It, Monoids, curry, Monads, Either, Left, Right

Act on It

Eric Evans coined the term supple model to describe a design that starts with raw materials that are hammered into form as our domain understanding deepens. In functional programming, those raw materials are small, composable functions—each solving a narrow piece of the domain. Through composition, we hammer those fragments into structure, shaping them as our understanding evolves.

How might you hammer out the following situations?
• You only need to know whether the patron is eligible for the ride, not why.
How might you reduce multiple messages to a single "Alice is not eligible"?
• How might you validate a patron, but only if the ride is online?
• A patron might not qualify for the fast lane but still be allowed to ride.
How might you return either "Alice is not eligible for this ride" or "Alice can ride, but
not through the fast lane"?
# Patron is just ineligible.
  def validate_answer_a(%Patron{} = patron, %Ride{} = ride) do
    validate_vip_or_pass = curry(&ensure_vip_or_fast_pass/2)

    validate_eligibility =
      curry(fn p, r ->
        validate_eligibility(p, r)
        |> Either.map_left(fn _ ->
          "#{Patron.get_name(p)} is not eligible for this ride"
        end)
      end)

    Either.validate(
      ride,
      [
        validate_eligibility.(patron),
        validate_vip_or_pass.(patron),
        &Ride.ensure_online/1
      ]
    )
    |> map(fn _ -> patron end)
  end

# Patron only if ride is online.

  def validate_answer_b(%Patron{} = patron, %Ride{} = ride) do
    validate_vip_or_pass = curry(&ensure_vip_or_fast_pass/2)
    validate_eligibility = curry(&validate_eligibility/2)

    validate_fast_lane =
      Either.validate(
        ride,
        [
          validate_eligibility.(patron),
          validate_vip_or_pass.(patron)
        ]
      )

    Ride.ensure_online(ride)
    |> Either.map_left(fn message -> [message] end)
    |> ap(validate_fast_lane)
    |> map(fn _ -> patron end)
  end

# Add more feedback.
  def validate_answer_c(%Patron{} = patron, %Ride{} = ride) do
    validate_fast_lane =
      curry_r(fn p, r ->
        ensure_vip_or_fast_pass(p, r)
        |> Either.map_left(fn _ ->
          "#{Patron.get_name(p)} can ride, but not through the fast lane"
        end)
      end)

    validate_eligibility =
      curry_r(fn p, r ->
        validate_eligibility(p, r)
        |> Either.map_left(fn _ ->
          "#{Patron.get_name(p)} is not eligible for this ride"
        end)
      end)

    Either.validate(
      patron,
      [
        validate_eligibility.(ride),
        validate_fast_lane.(ride)
      ]
    )
    |> map(fn _ ->
      "#{Patron.get_name(patron)} can enter the fast lane"
    end)
    |> Either.map_left(fn [first | _] -> first end)
  end

Run It