pzp1997 / assoc-list / AssocList

An association list is a list of tuples that map unique keys to values. The keys can be of any type (so long as it has a reasonable definition for equality). This includes pretty much everything except for functions and things that contain functions.

All functions in this module are "stack safe," which means that your program won't crash from recursing over large association lists. You can read Evan Czaplicki's document on tail-call elimination for more information about this topic.

Dictionaries


type Dict a b

A dictionary of keys and values. So a Dict String User is a dictionary that lets you look up a String (such as user names) and find the associated User.

import AssocList as Dict exposing (Dict)

users : Dict String User
users =
    Dict.fromList
        [ ( "Alice", User "Alice" 28 1.65 )
        , ( "Bob", User "Bob" 19 1.82 )
        , ( "Chuck", User "Chuck" 33 1.75 )
        ]

type alias User =
    { name : String
    , age : Int
    , height : Float
    }

Build

empty : Dict k v

Create an empty dictionary.

singleton : k -> v -> Dict k v

Create a dictionary with one key-value pair.

insert : k -> v -> Dict k v -> Dict k v

Insert a key-value pair into a dictionary. Replaces value when there is a collision.

update : k -> (Maybe v -> Maybe v) -> Dict k v -> Dict k v

Update the value of a dictionary for a specific key with a given function.

If you are using this module as an ordered dictionary, please note that if you are replacing the value of an existing entry, the entry will remain where it is in the insertion order. (If you do want to change the insertion order, consider using get in conjunction with insert instead.)

remove : k -> Dict k v -> Dict k v

Remove a key-value pair from a dictionary. If the key is not found, no changes are made.

Query

isEmpty : Dict k v -> Basics.Bool

Determine if a dictionary is empty.

isEmpty empty
--> True

member : k -> Dict k v -> Basics.Bool

Determine if a key is in a dictionary.

get : k -> Dict k v -> Maybe v

Get the value associated with a key. If the key is not found, return Nothing. This is useful when you are not sure if a key will be in the dictionary.

type Animal
    = Cat
    | Mouse

animals : Dict String Animal
animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]

get "Tom" animals
--> Just Cat

get "Jerry" animals
--> Just Mouse

get "Spike" animals
--> Nothing

size : Dict k v -> Basics.Int

Determine the number of key-value pairs in the dictionary.

size (fromList [ ( "a", 1 ), ( "b", 2 ), ( "c", 3 ) ])
--> 3

size (insert 1 "b" (singleton 1 "a"))
--> 1

eq : Dict k v -> Dict k v -> Basics.Bool

Compare two dictionaries for equality, ignoring insertion order. Dictionaries are defined to be equal when they have identical key-value pairs where keys and values are compared using the built-in equality operator.

You should almost never use the built-in equality operator to compare dictionaries from this module since association lists have no canonical form.

eq
    (fromList [ ( "a", 1 ), ( "b", 2 ) ])
    (fromList [ ( "b", 2 ), ( "a", 1 ) ])
--> True

Lists

keys : Dict k v -> List k

Get all of the keys in a dictionary, in the order that they were inserted with the most recently inserted key at the head of the list.

keys (fromList [ ( 0, "Alice" ), ( 1, "Bob" ) ])
--> [ 1, 0 ]

values : Dict k v -> List v

Get all of the values in a dictionary, in the order that they were inserted with the most recently inserted value at the head of the list.

values (fromList [ ( 0, "Alice" ), ( 1, "Bob" ) ])
--> [ "Bob", "Alice" ]

toList : Dict k v -> List ( k, v )

Convert a dictionary into an association list of key-value pairs, in the order that they were inserted with the most recently inserted entry at the head of the list.

fromList : List ( k, v ) -> Dict k v

Convert an association list into a dictionary. The elements are inserted from left to right. (If you want to insert the elements from right to left, you can simply call List.reverse on the input before passing it to fromList.)

Transform

map : (k -> a -> b) -> Dict k a -> Dict k b

Apply a function to all values in a dictionary.

foldl : (k -> v -> b -> b) -> b -> Dict k v -> b

Fold over the key-value pairs in a dictionary from most recently inserted to least recently inserted.

users : Dict String Int
users =
    empty
        |> insert "Alice" 28
        |> insert "Bob" 19
        |> insert "Chuck" 33

foldl (\name age result -> age :: result) [] users
--> [28,19,33]

foldr : (k -> v -> b -> b) -> b -> Dict k v -> b

Fold over the key-value pairs in a dictionary from least recently inserted to most recently insered.

users : Dict String Int
users =
    empty
        |> insert "Alice" 28
        |> insert "Bob" 19
        |> insert "Chuck" 33

foldr (\name age result -> age :: result) [] users
--> [33,19,28]

filter : (k -> v -> Basics.Bool) -> Dict k v -> Dict k v

Keep only the key-value pairs that pass the given test.

partition : (k -> v -> Basics.Bool) -> Dict k v -> ( Dict k v, Dict k v )

Partition a dictionary according to some test. The first dictionary contains all key-value pairs which passed the test, and the second contains the pairs that did not.

Combine

union : Dict k v -> Dict k v -> Dict k v

Combine two dictionaries. If there is a collision, preference is given to the first dictionary.

If you are using this module as an ordered dictionary, the ordering of the output dictionary will be all the entries of the first dictionary (from most recently inserted to least recently inserted) followed by all the entries of the second dictionary (from most recently inserted to least recently inserted).

intersect : Dict k v -> Dict k v -> Dict k v

Keep a key-value pair when its key appears in the second dictionary. Preference is given to values in the first dictionary.

diff : Dict k a -> Dict k b -> Dict k a

Keep a key-value pair when its key does not appear in the second dictionary.

merge : (k -> a -> result -> result) -> (k -> a -> b -> result -> result) -> (k -> b -> result -> result) -> Dict k a -> Dict k b -> result -> result

The most general way of combining two dictionaries. You provide three accumulators for when a given key appears:

  1. Only in the left dictionary.
  2. In both dictionaries.
  3. Only in the right dictionary.

You then traverse all the keys in the following order, building up whatever you want:

  1. All the keys that appear only in the right dictionary from least recently inserted to most recently inserted.
  2. All the keys in the left dictionary from least recently inserted to most recently inserted (without regard to whether they appear only in the left dictionary or in both dictionaries).