indique/elm-pairdict/2.1.0

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 { left= 'a', right= 'A' }
  |>insert { left= 'b', right= 'B' }
  |>insert { left= 'c', right= '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 conveniently from Pair-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.

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 { left= 'b', right= 'B' }
  , ( 'a', 'A' ) --insert { left= 'a', right= 'A' }
  , ( 'b', 'C' ) --ignored, as the left value already exists
  , ( 'c', 'A' ) --ignored, as the right value already exists
  , ( 'c', 'C' ) --insert { left= 'c', right= '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 { left= 'a', right= 'A' }
  |>insert { left= 'b', right= '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 { left= 'a', right= 'A' }
  |>insert { left= 'b', right= 'B' }
  |>insert { left= 'c', right= 'C' }


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 { left= "(", right= ")" }
|>insert { right= "fire", left= "water" }
--fromList
--  [ ( "(", ")" ) ( "water", "fire" ) ]
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 "("
--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 ")"
--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
swapLeftRight : PairDict left right -> PairDict right left

What has been left → right, right → left.

upperToLower=
  fromList
    [ ( 'A', 'a' ), ( 'B', 'b' ) ]
lowerToUpper=
  upperToLower |>swapLeftRight
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
      (\{left,right}->
        { left= String.fromInt left
        , right= right
        }
      )
  |>insert { left= "+", right= "plus" }
dictFromLeft : PairDict left right -> Dict left right

No cost: An association-Dict, which you can access only from the left

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

No cost: An association-Dict, which you can access only from the left

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

Convert a PairDict to a Json.Encode.Value.

somePairDict=
  empty
  |>insert { left= 1, right= 11 }
  |>insert { left= 2, right= 22 }
Encode.encode 1
  (encode
    Encode.int Encode.int
    somePairDict
  )
{->
"""
[
 {
  \"left\": 2,
  \"right\": 22
 },
 {
  \"left\": 1,
  \"right\": 11
 }
]
"""
-}