Home Posts Post Search Tag Search

Advanced Functional Elixir - 01 - Model Real-World Data
Published on: 2026-03-04 Tags: elixir, Blog, Side Project, Advanced Functional Programming, FunPark, Domain Driven Design

1. Build FunPark: Model Real-World Data

For this project we will be building a functional program for a theme park. We will start off with trying to build a Ride, Patron, and FastPass module. Let’s get started.

Define the Ride Model

For the Ride we want to have a few parameters: unique ID, name, min. height, age requirements, online, wait time, tags [:dark, :thrill, :etc].

  defstruct id: nil,
            name: "Unknown Ride",
            min_age: 0,
            min_height: 0,
            wait_time: 0,
            online: true,
            tags: []

  def make(name, opts \\ []) when is_binary(name) do
    %__MODULE__{
      id: :erlang.unique_integer([:positive]),
      name: name,
      min_age: Keyword.get(opts, :min_age, 0),
      min_height: Keyword.get(opts, :min_height, 0),
      wait_time: Keyword.get(opts, :wait_time, 0),
      online: Keyword.get(opts, :online, true),
      tags: Keyword.get(opts, :tags, [])
    }
  end

Run It

iex(1)> FunPark.Ride.make("Tea Cup", wait_time: 10, tags: [:family_friendly])
%FunPark.Ride{
  id: 898,
  name: "Tea Cup",
  min_age: 0,
  min_height: 0,
  wait_time: 10,
  online: true,
  tags: [:family_friendly]
}

iex(2)> # Lets also create a dark_mansion ride.
iex(3)> dark_mansion = FunPark.Ride.make(
...(3)> "Dark Mansion",
...(3)> min_age: 14,
...(3)> tags: [:dark]
...(3)> )
%FunPark.Ride{
  id: 2243,
  name: "Dark Mansion",
  min_age: 14,
  min_height: 0,
  wait_time: 0,
  online: true,
  tags: [:dark]
}

I really like that fact that we use opts to get all the optional params from the map that we pass in.

Implement FastPasses for Priority Access

Okay so now we want to implement a fast pass for the park as well it will have the following parameters: id, ride, time.

  defstruct id: nil,
            ride: nil,
            time: nil

  def make(%Ride{} = ride, %DateTime{} = time) do
    %__MODULE__{
      id: :erlang.unique_integer([:positive]),
      ride: ride,
      time: time
    }
  end

Run It

iex(4)> datetime = DateTime.new!(~D[2025-06-01], ~T[13:00:00])
~U[2025-06-01 13:00:00Z]
iex(5)> fast_pass = FunPark.FastPass.make(dark_mansion, datetime)
%FunPark.FastPass{
  id: 2435,
  ride: %FunPark.Ride{
    id: 2243,
    name: "Dark Mansion",
    min_age: 14,
    min_height: 0,
    wait_time: 0,
    online: true,
    tags: [:dark]
  },
  time: ~U[2025-06-01 13:00:00Z]
}

We see a different use of the pattern match here so that we can pass in a map and then just pull those values that we need out. There is not guards.

Model the Patrons

For the Patrons we will need to have the following params: id, name, age, height, ticket_tier, fast_passes, reward_points, likes, dislikes.

  defstruct id: nil,
            name: nil,
            age: 0,
            height: 0,
            ticket_tier: :basic,
            fast_passes: [],
            reward_points: 0,
            likes: [],
            dislikes: []

  def make(name, age, height, opts \\ [])
      when is_bitstring(name) and
             is_integer(age) and
             is_integer(height) and
             age > 0 and
             height > 0 do
    %__MODULE__{
      id: :erlang.unique_integer([:positive]),
      name: name,
      age: age,
      height: height,
      ticket_tier: Keyword.get(opts, :ticket_tier, :basic),
      fast_passes: Keyword.get(opts, :fast_passes, []),
      reward_points: Keyword.get(opts, :reward_points, 0),
      likes: Keyword.get(opts, :likes, []),
      dislikes: Keyword.get(opts, :dislikes, [])
    }
  end

Run It

iex(6)> FunPark.Patron.make("Alice", 15, 120, fast_passes: [fast_pass])
%FunPark.Patron{
  id: 2499,
  name: "Alice",
  age: 15,
  height: 120,
  ticket_tier: :basic,
  fast_passes: [
    %FunPark.FastPass{
      id: 2435,
      ride: %FunPark.Ride{
        id: 2243,
        name: "Dark Mansion",
        min_age: 14,
        min_height: 0,
        wait_time: 0,
        online: true,
        tags: [:dark]
      },
      time: ~U[2025-06-01 13:00:00Z]
    }
  ],
  reward_points: 0,
  likes: [],
  dislikes: []
}

Okay so we went back to the Keyword.get/3 but we also have some needed values passed as params for the make/4. This works but you need to keep in mind that there are values that need to be passed to make the function work.

Speak the Language

So one thing that will really help a new programmer is to make sure that you speak the language of the rest of the team. We heard that a guest is a Patron so the module is made to reflect that.

What You’ve Learned

We have built the basic foundation of the park. We have Ride, Patron, and FastPass. We aren’t trying to build the entire software all at once and we are not married to any one aspect because we know it might change.