edkelly303 / elm-any-type-collections / Any.Dict

Data


type Dict k v comparable

A replacement for elm/core's Dict data structure; the difference is that keys can be of any type, not just comparable.

(When I say "any" type, there's one proviso: you must be able to provide a pair of functions that can convert your key type into a comparable and back again. So this won't work with functions, but it will work with custom types.)

Interface


type alias Interface k v v2 output comparable =
{ empty : Dict k v comparable
, singleton : k -> v -> Dict k v comparable
, insert : k -> v -> Dict k v comparable -> Dict k v comparable
, update : k -> (Maybe v -> Maybe v) -> Dict k v comparable -> Dict k v comparable
, remove : k -> Dict k v comparable -> Dict k v comparable
, isEmpty : Dict k v comparable -> Basics.Bool
, member : k -> Dict k v comparable -> Basics.Bool
, get : k -> Dict k v comparable -> Maybe v
, size : Dict k v comparable -> Basics.Int
, keys : Dict k v comparable -> List k
, values : Dict k v comparable -> List v
, toList : Dict k v comparable -> List ( k
, v )
, fromList : List ( k
, v ) -> Dict k v comparable
, map : (k -> v -> v2) -> Dict k v comparable -> Dict k v2 comparable
, foldl : (k -> v -> output -> output) -> output -> Dict k v comparable -> output
, foldr : (k -> v -> output -> output) -> output -> Dict k v comparable -> output
, filter : (k -> v -> Basics.Bool) -> Dict k v comparable -> Dict k v comparable
, partition : (k -> v -> Basics.Bool) -> Dict k v comparable -> ( Dict k v comparable
, Dict k v comparable )
, union : Dict k v comparable -> Dict k v comparable -> Dict k v comparable
, intersect : Dict k v comparable -> Dict k v comparable -> Dict k v comparable
, diff : Dict k v comparable -> Dict k v comparable -> Dict k v comparable
, merge : (k -> v -> output -> output) -> (k -> v -> v2 -> output -> output) -> (k -> v2 -> output -> output) -> Dict k v comparable -> Dict k v2 comparable -> output -> output 
}

An Interface is just a record containing functions that mirror the API of the elm/core Dict module.

The type signature might look daunting, but in practice you can ignore it.

All you need to remember is that if you create an Interface called dict, you can use it just like the elm-core Dict API:

-- elm/core
myDict =
    Dict.singleton 1 "hello"

-- edkelly303/elm-any-type-collections
dict =
    Any.Dict.makeInterface
        { fromComparable = identity
        , toComparable = identity
        }

myDict =
    dict.singleton 1 "hello"

makeInterface : { toComparable : k -> comparable, fromComparable : comparable -> k } -> Interface k v v2 output comparable

Use makeInterface to define an Interface for your custom Dict type. You need to supply two functions:

  1. toComparable, which converts your key type into any comparable type (i.e. Int, String, Float, or a tuple containing only comparable types)
  2. fromComparable, which converts that same comparable type back into your key type.

It's a good idea to define the Interface as a top-level value. Once you've defined the Interface, you can use it anywhere in your code without needing to pass it explicitly to your functions.

For example, here we define the Interface as a top-level value called colourDictInterface:

type Colour
    = Red
    | Green
    | Blue

colourToInt c =
    case c of
        Red ->
            0

        Green ->
            1

        Blue ->
            2

colourFromInt i =
    case i of
        0 ->
            Red

        1 ->
            Green

        _ ->
            Blue

colourDictInterface =
    makeInterface
        { toComparable = colourToInt
        , fromComparable = colourFromInt
        }

myColourDict =
    colourDictInterface.fromList
        [ ( Red, "This is red!" )
        , ( Blue, "This is blue!" )
        ]

thisIsTrue : Bool
thisIsTrue =
    colourDictInterface.get Red myColourDict
        == Just "This is red!"