Funx.List (funx v0.8.0)

View Source

Run in Livebook

The Funx.List module provides utility functions for working with lists while respecting Eq and Ord instances. This allows for set-like operations, uniqueness constraints, and sorted collections that align with functional programming principles.

Features

  • Equality-based Operations: Use Eq instances to compare elements for uniqueness, intersection, and difference.
  • Ordering Functions: Leverage Ord instances to sort and enforce uniqueness in sorted collections.
  • Set Operations: Perform union, intersection, difference, and symmetric difference while preserving custom equality logic.
  • Subset & Superset Checks: Verify relationships between lists in terms of inclusion.
  • Functional Constructs: Implements Monad and Foldable protocols for lists, supporting mapping, binding, and folding.

Usage Overview

  1. Deduplicate: Use uniq/1 to remove duplicates based on Eq.
  2. Combine: Use union/2 to merge lists without duplicates.
  3. Filter: Use intersection/2 or difference/2 for set operations.
  4. Sort: Use sort/2 or strict_sort/2 with Ord instances.
  5. Check Membership: Use subset?/2 or superset?/2 to verify inclusion relationships.
  6. Find Extremes: Use min/2, max/2 for safe min/max, or min!/2, max!/2 to raise on empty.

Equality-Based Operations

Ordering Functions

Set Operations

  • subset?/2: Checks if one list is a subset of another.
  • superset?/2: Checks if one list is a superset of another.

Min/Max Operations

  • min/2: Returns the minimum element wrapped in Maybe.
  • min!/2: Returns the minimum element, raises on empty list.
  • max/2: Returns the maximum element wrapped in Maybe.
  • max!/2: Returns the maximum element, raises on empty list.

Monad Implementation

  • map/2: Transforms list elements.
  • bind/2: Applies a function returning lists and flattens the result.
  • ap/2: Applies functions in a list to elements in another list.

Foldable Implementation

  • fold_l/3: Performs left-associative folding.
  • fold_r/3: Performs right-associative folding.

Summary

Functions

Concatenates a list of lists from left to right.

Returns the difference of two lists.

Returns true if the given value is an element of the list under the provided Eq.

Returns the head of a list wrapped in Maybe.Just, or Maybe.Nothing if empty.

Returns the head of a list.

Returns the intersection of two lists.

Returns the maximum element in a list according to the given ordering.

Returns the maximum element in a list according to the given ordering.

Returns the minimum element in a list according to the given ordering.

Returns the minimum element in a list according to the given ordering.

Sorts a list using the given ordering module.

Sorts a list while ensuring uniqueness.

Checks if the first list is a subset of the second.

Checks if the first list is a superset of the second.

Returns the symmetric difference of two lists.

Returns the tail of a list.

Returns the union of two lists, removing duplicates.

Removes duplicate elements from a list based on the given equality module.

Functions

concat(list)

@spec concat([[term()]]) :: [term()]

Concatenates a list of lists from left to right.

This uses the ListConcat monoid, preserving the original order of elements.

Examples

iex> Funx.List.concat([[1], [2, 3], [4]])
[1, 2, 3, 4]

difference(list1, list2, eq \\ Funx.Eq.Protocol)

@spec difference([term()], [term()], Funx.Eq.eq_t()) :: [term()]

Returns the difference of two lists.

Examples

iex> Funx.List.difference([1, 2, 3, 4], [3, 4, 5])
[1, 2]

elem?(list, value, eq \\ Funx.Eq.Protocol)

@spec elem?(term(), [term()], Funx.Eq.eq_t()) :: boolean()

Returns true if the given value is an element of the list under the provided Eq.

This is the Eq-based equivalent of Haskell's elem.

Examples

iex> Funx.List.elem?([1, 2, 3], 1)
true

iex> Funx.List.elem?([1, 3], 2)
false

head(list)

@spec head([a]) :: Funx.Monad.Maybe.t(a) when a: term()

Returns the head of a list wrapped in Maybe.Just, or Maybe.Nothing if empty.

This is a safe version of hd/1 that returns Maybe instead of raising.

Examples

iex> Funx.List.head([1, 2, 3])
%Funx.Monad.Maybe.Just{value: 1}

iex> Funx.List.head([])
%Funx.Monad.Maybe.Nothing{}

iex> Funx.List.head("not a list")
%Funx.Monad.Maybe.Nothing{}

head!(list)

@spec head!([a]) :: a when a: term()

Returns the head of a list.

Raises ArgumentError if the list is empty or not a list.

Examples

iex> Funx.List.head!([1, 2, 3])
1

iex> Funx.List.head!([42])
42

intersection(list1, list2, eq \\ Funx.Eq.Protocol)

@spec intersection([term()], [term()], Funx.Eq.eq_t()) :: [term()]

Returns the intersection of two lists.

Examples

iex> Funx.List.intersection([1, 2, 3, 4], [3, 4, 5])
[3, 4]

max(list, ord \\ Funx.Ord.Protocol)

@spec max([a], Funx.Ord.ord_t()) :: Funx.Monad.Maybe.t(a) when a: term()

Returns the maximum element in a list according to the given ordering.

Returns Just(element) for non-empty lists, Nothing for empty lists.

This is a safe version that returns Maybe instead of raising. Use max!/2 if you want to raise on empty lists.

Examples

iex> Funx.List.max([3, 1, 4, 1, 5])
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.List.max([])
%Funx.Monad.Maybe.Nothing{}

iex> ord = Funx.Ord.contramap(&String.length/1)
iex> Funx.List.max(["cat", "elephant", "ox"], ord)
%Funx.Monad.Maybe.Just{value: "elephant"}

max!(list, ord \\ Funx.Ord.Protocol)

@spec max!([a], Funx.Ord.ord_t()) :: a when a: term()

Returns the maximum element in a list according to the given ordering.

Raises Enum.EmptyError if the list is empty.

Examples

iex> Funx.List.max!([3, 1, 4, 1, 5])
5

iex> ord = Funx.Ord.contramap(&String.length/1)
iex> Funx.List.max!(["cat", "elephant", "ox"], ord)
"elephant"

min(list, ord \\ Funx.Ord.Protocol)

@spec min([a], Funx.Ord.ord_t()) :: Funx.Monad.Maybe.t(a) when a: term()

Returns the minimum element in a list according to the given ordering.

Returns Just(element) for non-empty lists, Nothing for empty lists.

This is a safe version that returns Maybe instead of raising. Use min!/2 if you want to raise on empty lists.

Examples

iex> Funx.List.min([3, 1, 4, 1, 5])
%Funx.Monad.Maybe.Just{value: 1}

iex> Funx.List.min([])
%Funx.Monad.Maybe.Nothing{}

iex> ord = Funx.Ord.contramap(&String.length/1)
iex> Funx.List.min(["cat", "elephant", "ox"], ord)
%Funx.Monad.Maybe.Just{value: "ox"}

min!(list, ord \\ Funx.Ord.Protocol)

@spec min!([a], Funx.Ord.ord_t()) :: a when a: term()

Returns the minimum element in a list according to the given ordering.

Raises Enum.EmptyError if the list is empty.

Examples

iex> Funx.List.min!([3, 1, 4, 1, 5])
1

iex> ord = Funx.Ord.contramap(&String.length/1)
iex> Funx.List.min!(["cat", "elephant", "ox"], ord)
"ox"

sort(list, ord \\ Funx.Ord.Protocol)

@spec sort([term()], Funx.Ord.ord_t()) :: [term()]

Sorts a list using the given ordering module.

Examples

iex> Funx.List.sort([3, 1, 4, 1, 5])
[1, 1, 3, 4, 5]

strict_sort(list, ord \\ Funx.Ord.Protocol)

@spec strict_sort([term()], Funx.Ord.ord_t()) :: [term()]

Sorts a list while ensuring uniqueness.

Examples

iex> Funx.List.strict_sort([3, 1, 4, 1, 5])
[1, 3, 4, 5]

subset?(small, large, eq \\ Funx.Eq.Protocol)

@spec subset?([term()], [term()], Funx.Eq.eq_t()) :: boolean()

Checks if the first list is a subset of the second.

Examples

iex> Funx.List.subset?([1, 2], [1, 2, 3, 4])
true

iex> Funx.List.subset?([1, 5], [1, 2, 3, 4])
false

superset?(large, small, eq \\ Funx.Eq.Protocol)

@spec superset?([term()], [term()], Funx.Eq.eq_t()) :: boolean()

Checks if the first list is a superset of the second.

Examples

iex> Funx.List.superset?([1, 2, 3, 4], [1, 2])
true

iex> Funx.List.superset?([1, 2, 3, 4], [1, 5])
false

symmetric_difference(list1, list2, eq \\ Funx.Eq.Protocol)

@spec symmetric_difference([term()], [term()], Funx.Eq.eq_t()) :: [term()]

Returns the symmetric difference of two lists.

Examples

iex> Funx.List.symmetric_difference([1, 2, 3], [3, 4, 5])
[1, 2, 4, 5]

tail(list)

@spec tail([a]) :: [a] when a: term()

Returns the tail of a list.

The tail of an empty list is an empty list.

Examples

iex> Funx.List.tail([1, 2, 3])
[2, 3]

iex> Funx.List.tail([1])
[]

iex> Funx.List.tail([])
[]

union(list1, list2, eq \\ Funx.Eq.Protocol)

@spec union([term()], [term()], Funx.Eq.eq_t()) :: [term()]

Returns the union of two lists, removing duplicates.

Examples

iex> Funx.List.union([1, 2, 3], [3, 4, 5])
[1, 2, 3, 4, 5]

uniq(list, eq \\ Funx.Eq.Protocol)

@spec uniq([term()], Funx.Eq.eq_t()) :: [term()]

Removes duplicate elements from a list based on the given equality module.

Examples

iex> Funx.List.uniq([1, 2, 2, 3, 1, 4, 5])
[1, 2, 3, 4, 5]