defmodule LinkedList do @opaque t :: tuple() @doc """ Construct a new LinkedList """ @spec new() :: t def new() do [] end @doc """ Push an item onto a LinkedList """ @spec push(t, any()) :: t def push(list, elem) do [elem | list] end @doc """ Calculate the length of a LinkedList """ @spec length(t) :: non_neg_integer() def length(list) do Enum.count(list) end @doc """ Determine if a LinkedList is empty """ @spec empty?(t) :: boolean() def empty?(list) do Enum.empty?(list) end @doc """ Get the value of a head of the LinkedList """ @spec peek(t) :: {:ok, any()} | {:error, :empty_list} def peek(list) do cond do empty?(list) -> {:error, :empty_list} true -> {:ok, hd(list)} end end @doc """ Get tail of a LinkedList """ @spec tail(t) :: {:ok, t} | {:error, :empty_list} def tail(list) do cond do empty?(list) -> {:error, :empty_list} true -> {:ok, tl(list)} end end @doc """ Remove the head from a LinkedList """ @spec pop(t) :: {:ok, any(), t} | {:error, :empty_list} def pop(list) do cond do empty?(list) -> {:error, :empty_list} true -> [hd | tail] = list {:ok, hd, tail} end end @doc """ Construct a LinkedList from a stdlib List """ @spec from_list(list()) :: t def from_list(list) do list end @doc """ Construct a stdlib List LinkedList from a LinkedList """ @spec to_list(t) :: list() def to_list(list) do Enum.to_list(list) end @doc """ Reverse a LinkedList """ @spec reverse(t) :: t def reverse(list) do # Your implementation here... Enum.reverse(list) end end