indique/elm-pairdict/4.0.1

NOTE: the latest version is 6.0.3

PairDict

type PairDict left right

Want to look up value-pairs from the left or the right?

Like assoc-list, a PairDict allows for anything as left or right values except for functions and things that contain functions.

Example: cased letters

lowerUppercaseLetters=
  empty
  |>insert ( 'a', 'A' )
  |>insert ( 'b', 'B' )
  |>insert ( 'c', 'C' )


upperCase char=
  rightOf char lowerUppercaseLetters
equal : PairDict left right -> PairDict left right -> Bool

using (==) built-in equality is often not useful in the context of association-dicts.

Ignoring insertion order: do these 2 PairDicts have the same size and identical Pairs?

letterCodes=
  fromList [ ( 'a', 0 ), ( 'b', 1 ) ]
fancyCompetingLetterCodes=
  fromList [ ( 'b', 1 ), ( 'a', 0 ) ]


equal
  letterCodes
  fancyCompetingLetterCodes
--> True

create

empty : PairDict left right

A PairDict with no elements

fromDict : Dict left right -> PairDict left right

Create a PairDict from a association-Dict. left is the key, right is the value. If multiple equal keys or values are present, the value first in the Dict is prefered.

lowerToUpperLetters=
  AssocList.Dict.empty
  |>AssocList.Dict.insert 'a' 'A'
  |>AssocList.Dict.insert 'b' 'B'


lowerUpperLetters= fromDict lowerToUpperLetters
fromList : List ( left, right ) -> PairDict left right

Create a PairDict conveniently from Tuples. left is the first, right is the second. If right or left values are given multiple times, the value first in the List is prefered.

fromList
  [ ( 'b', 'B' ) --insert ( 'b', 'B' )
  , ( 'a', 'A' ) --insert ( 'a', 'A' )
  , ( 'b', 'C' ) --ignored, as the left value already exists
  , ( 'c', 'A' ) --ignored, as the right value already exists
  , ( 'c', 'C' ) --insert ( 'c', 'C' )
  ]
decode : Decoder left -> Decoder right -> Decoder (PairDict left right)

A Json.Decode.Decoder for PairDicts, encoded by encodePair.

The order of insertion is not reconstructed (see equal)

"""
[
 {
  \"left\": 2,
  \"right\": 22
 },
 {
  \"left\": 1,
  \"right\": 11
 }
]
"""
|>Decode.decodeString
    (decode Decode.int Decode.int)

Ok (fromList [ ( 1, 11 ), ( 2, 22 ) ])

access

rightOf : left -> PairDict left right -> Maybe right

Just the right value if the left value is present in the PairDict, else Nothing

casedLetters=
  empty
  |>insert ( 'a', 'A' )
  |>insert ( 'b', 'B' )


lowerCase char=
  leftOf char casedLetters
leftOf : right -> PairDict left right -> Maybe left

Just the right value if the left value is present in the PairDict, else Nothing

casedLetters=
  empty
  |>insert ( 'a', 'A' )
  |>insert ( 'b', 'B' )


upperCase char=
  rightOf char casedLetters

properties

size : PairDict left right -> Int

How many pairs there are.

size empty

0

size
  (fromList
    (List.range 0 41 |>List.map (\i-> ( i, i )))
  )

42

in

insert : Pair left right -> PairDict left right -> PairDict left right

Put in a left-right-Pair.

If either value is already present, the PairDict is unchanged.

empty
|>insert ( 'b', 'B' ) --puts it in 
|>insert ( 'a', 'A' ) --puts it in
|>insert ( 'b', 'C' ) --ignored, the left value already exists
|>insert ( 'c', 'A' ) --ignored, the right value already exists
|>insert ( 'c', 'C' ) --puts it in
union : PairDict left right -> PairDict left right -> PairDict left right

Merge 2 PairDicts. If a value on the left or right is present, prefer the second dict.

numberNamedOperators=
  fromList
    [ ( '+', "plus" )
    , ( '-', "minus" )
    ]
customNamedOperators=
  fromList
    [ ( '∧', "and" )
    , ( '∨', "or" )
    , ( '-', "negate" )
    ]
validNamedOperators=
  union
    custumNamedOperators --has a '-' left
    numberOperatorNames --preferred → its '-'-Pair is inserted

out

removeLeft : left -> PairDict left right -> PairDict left right

remove left-right pair. If left does not exist, the PairDict is unchanged

empty
|>insert "(" ")"
|>removeLeft ")" --unchanged, ")" is not a left value
|>removeLeft "(" --removes ( "(", ")" )
--empty
removeRight : right -> PairDict left right -> PairDict left right

remove left-right pair. If right does not exist, the PairDict is unchanged

empty
|>insert ( "(", ")" )
|>removeRight "(" --unchanged, "(" is not a right value
|>removeRight ")" --removes ( "(", ")" )
--empty

shape

lefts : PairDict left right -> List left

values on the left

brackets=
  fromList [ ( '(', ')' ), ( '{', '}' ) ]
opening= lefts brackets
rights : PairDict left right -> List right

values on the right

brackets=
  fromList [ ( '(', ')' ), ( '{', '}' ) ]
closing= rights brackets
fold : (Pair left right -> acc -> acc) -> acc -> PairDict left right -> acc

Reduce the left-right Pairs from most recently inserted to least recently inserted. A fold in the other direction doesn't exist, as association-Dicts should rarely rely on order (see equal)

brackets=
  fromList
    [ ( '(', ')' )
    , ( '{', '}' )
    ]
openingAndClosing=
  brackets
  |>fold
      (\( left, right ) acc->
        acc ++[ String.fromList [ left, right ] ]
      )
      []

[ "{}", "()" ]

map :
(Pair left right -> Pair resultLeft resultRight)
-> PairDict left right
-> PairDict resultLeft resultRight

map pairs

digitNames=
  fromList
    [ ( 0, "zero" )
    , ( 1, "one" )
    ]
mathSymbolNames=
  digitNames
  |>map (Pair.mapLeft String.fromInt)
  |>insert ( "+", "plus" )
toDict : PairDict left right -> Dict left right

Convert to an association-Dict, which you can access only from the left

casedLetters=
  fromList
    [ ( 'A', 'a' ), ( 'B', 'b' ) ]
lowerFromUpper=
  casedLetters |>dictFromLeft
encode : (left -> Value) -> (right -> Value) -> PairDict left right -> Value

Convert a PairDict to a Json.Encode.Value.

somePairDict=
  empty
  |>insert ( 1, 11 )
  |>insert ( 2, 22 )
Encode.encode 1
  (encode
    Encode.int Encode.int
    somePairDict
  )




"""
[
 {
  \"left\": 2,
  \"right\": 22
 },
 {
  \"left\": 1,
  \"right\": 11
 }
]
"""