[{"name":"KeySet","comment":" Lookup with one key\n\n@docs KeySet\n@docs Sorting, sortingKey\n\n\n## create\n\n[`Emptiable.empty`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable#empty),\n\n@docs only, fromStack, fromList\n\n\n## scan\n\n@docs size, element, end\n\n\n## alter\n\n@docs insert, elementRemove, elementAlter\n@docs map, mapTry\n\n\n## combine\n\n@docs unifyWith, except, intersect\n@docs fold2From, FirstOrSecondOrBoth\n\n\n## transform\n\n@docs toList\n@docs foldFrom, foldOnto, fold\n\n","unions":[{"name":"FirstOrSecondOrBoth","comment":" Unresolved element state while merging a \"first\" and \"second\" structure\n\n  - only in the `First` structure\n  - only in the `Second` structure\n  - in both `FirstSecond`\n\n`FirstSecond` has a tuple instead of a more descriptive record to make matching easier\n\n","args":["first","second"],"cases":[["First",["first"]],["Second",["second"]],["FirstSecond",["( first, second )"]]]}],"aliases":[{"name":"KeySet","comment":" 🗃️ Non-empty AVL-tree-based look-up. Elements and keys can be of any type\n\n[`insert`](#insert), [`elementRemove`](#elementRemove), [`element`](#element), [`end`](#end) runtime is `log n`\n\n    import KeySet exposing (KeySet)\n    import Stack\n    import User exposing (User(..))\n\n    users : Emptiable (KeySet User User.ByName) never_\n    users =\n        KeySet.fromStack User.byName\n            (Stack.topBelow\n                (User { name = \"Alice\", age = 28, height = 1.65 })\n                [ User { name = \"Bob\", age = 19, height = 1.82 }\n                , User { name = \"Chuck\", age = 33, height = 1.75 }\n                ]\n            )\n\nwhere\n\n    module User exposing (ByName, User(..), byName)\n\n    import KeySet\n    import Order\n\n    type User\n        = User { name : String, age : Int, height : Float }\n\n    type ByName\n        = ByName\n\n    byName : KeySet.Sorting User String ByName\n    byName =\n        KeySet.sortingKey .name\n            { tag = ByName\n            , order = String.Order.greaterEarlier (Char.Order.alphabetically Case.lowerUpper)\n            }\n\n","args":["element","tag"],"type":"KeySet.Internal.KeySet element tag"},{"name":"Sorting","comment":" Configure what's considered a key inside a [`KeySet`](#KeySet)\n\nCreate using [`sortingKey`](#sortingKey), as shown in\n\n  - [`KeySet` example](#KeySet)\n  - [readme example](https://dark.elm.dmy.fr/packages/lue-bird/elm-keysset/latest/#KeySet)\n\nYou can just ignore the `Typed` thing but if you're curious → [`typed-value`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typed-value/latest/)\n\n","args":["element","key","tag"],"type":"Typed.Typed Typed.Checked tag Typed.Public { key : element -> key, keyOrder : Order.Ordering key }"}],"values":[{"name":"element","comment":" Access the element associated with a given key.\nIf no element with the given key is not present, `Emptiable.empty`\n\n    import Emptiable exposing (Emptiable, filled, fillMap)\n    import Stack\n    import KeySet exposing (KeySet)\n    import Case\n    import Char.Order\n    import String.Order\n\n    type alias Animal =\n        { name : String\n        , kind : AnimalKind\n        }\n\n    type AnimalKind\n        = Mouse\n        | Cat\n\n    animals : Emptiable (KeySet Animal { byName : () }) never_\n    animals =\n        KeySet.fromStack animalByName\n            (Stack.topBelow\n                { name = \"Tom\", kind = Cat }\n                [ { name = \"Jerry\", kind = Mouse }\n                ]\n            )\n\n    -- should be opaque and should use an opaque tag\n    animalByName : KeySet.Sorting Animal String { byName : () }\n    animalByName =\n        KeySet.sortingKey .name\n            { tag = { byName = () }\n            , order =\n                String.Order.greaterEarlier (Char.Order.alphabetically Case.lowerUpper)\n            }\n\n    animals |> KeySet.element animalByName \"Tom\" |> fillMap .kind\n    --> filled Cat\n\n    animals |> KeySet.element animalByName \"Jerry\" |> fillMap .kind\n    --> filled Mouse\n\n    animals |> KeySet.element animalByName \"Spike\" |> fillMap .kind\n    --> Emptiable.empty\n\n","type":"KeySet.Sorting element key tag -> key -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable element Possibly.Possibly"},{"name":"elementAlter","comment":" Change the element for a given key in a given way\n\n  - The input is the same as asking for the [`element`](#element) with the same key\n  - Outputting `empty` is the same as calling [`elementRemove`](#elementRemove) with the same key\n\nOperations with `Emptiable` that might be handy\n\n  - [`fillMap`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable#fillMap)\n  - [`fillMapFlat`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable#fillMapFlat)\n  - [`fillElseOnEmpty`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable#fillElseOnEmpty)\n  - [`filled`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable#filled)\n\n","type":"KeySet.Sorting element key tag -> key -> (Emptiable.Emptiable element Possibly.Possibly -> Emptiable.Emptiable element elementAlteredEmptyPossiblyOrNever) -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) elementAlteredEmptyPossiblyOrNever"},{"name":"elementRemove","comment":" Remove its element whose key matches the given one.\nIf the key is not found, no changes are made\n","type":"KeySet.Sorting element key tag -> key -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) Possibly.Possibly"},{"name":"end","comment":" Get the element associated with a key at the end looking in a given `Direction`\n\n  - minimum → `end Down`\n  - maximum → `end Up`\n\n[`KeySet`](#KeySet) is `empty` → Nothing\n\n    import Linear exposing (Direction(..))\n    import Emptiable exposing (Emptiable)\n    import Stack\n    import KeySet exposing (KeySet)\n    import Case\n    import Char.Order\n    import String.Order\n\n\n    type alias User =\n        { name : String\n        , age : Int\n        , height : Float\n        }\n\n    users : Emptiable (KeySet User { userByName : () }) never_\n    users =\n        KeySet.fromStack userByName\n            (Stack.topBelow\n                { name = \"Bob\", age = 19, height = 1.82 }\n                [ { name = \"Alice\", age = 28, height = 1.65 }\n                , { name = \"Chuck\", age = 33, height = 1.75 }\n                ]\n            )\n\n    -- ↓ and tag should be opaque\n    userByName : KeySet.Sorting User String { userByName : () }\n    userByName =\n        KeySet.sortingKey .name\n            { tag = { userByName = () }\n            , order =\n                String.Order.greaterEarlier (Char.Order.alphabetically Case.lowerUpper)\n            }\n\n    users |> KeySet.end Down\n    --> { name = \"Alice\", age = 28, height = 1.65 }\n\n    users |> KeySet.end Up\n    --> { name = \"Chuck\", age = 33, height = 1.75 }\n\nNotice how we safely avoided returning a `Maybe`\nthrough the use of [`Emptiable ... Never`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Emptiable)\n\nIf you don't know whether the [`KeySet`](#KeySet) will be empty\n\n    users\n        |> fillMap (\\us -> us |> filled |> KeySet.end Up)\n    --: Emptiable element Possibly\n\n","type":"Linear.Direction -> Emptiable.Emptiable (KeySet.KeySet element tag_) Basics.Never -> element"},{"name":"except","comment":" Keep only those elements whose keys don't appear in the given [`KeySet`](#KeySet)\n","type":"KeySet.Sorting element key_ tag -> Emptiable.Emptiable (KeySet.KeySet element tag) incomingPossiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) Possibly.Possibly"},{"name":"fold","comment":" Fold, starting from one end as the initial accumulation value,\nthen reducing what's accumulated in a given [`Direction`](https://package.elm-lang.org/packages/lue-bird/elm-linear-direction/latest/)\n\n    import Linear exposing (Direction(..))\n    import Stack\n    import KeySet\n    import Int.Order\n\n    KeySet.fromStack intIncreasing\n        (Stack.topBelow 1 [ 2, 8, 16 ])\n        |> KeySet.fold Down (\\n soFar -> soFar - n)\n    --> 5\n\n    -- ↓ and tag should be opaque\n    intIncreasing : KeySet.Sorting Int Int { increasing : () }\n    intIncreasing =\n        KeySet.sortingKey identity\n            { tag = { increasing = () }\n            , order = Int.Order.increasing\n            }\n\n","type":"Linear.Direction -> (element -> element -> element) -> Emptiable.Emptiable (KeySet.KeySet element tag_) Basics.Never -> element"},{"name":"fold2From","comment":" Most powerful way of combining 2 [`KeySet`](#KeySet)s\n\nTraverses all the keys from both [`KeySet`](#KeySet)s _from lowest to highest_,\naccumulating whatever you want\nfor when a key appears in either the [`FirstOrSecondOrBoth`](#FirstOrSecondOrBoth)\nof the [`KeySet`](#KeySet)s\n\nYou will find this as \"merge\" in most other dictionaries/sets\n\n","type":"accumulated -> (KeySet.FirstOrSecondOrBoth firstElement secondElement -> accumulated -> accumulated) -> { first : { sorting : KeySet.Sorting firstElement key firstTag, set : Emptiable.Emptiable (KeySet.KeySet firstElement firstTag) firstPossiblyOrNever_ }, second : { sorting : KeySet.Sorting secondElement key secondTag, set : Emptiable.Emptiable (KeySet.KeySet secondElement secondTag) secondPossiblyOrNever_ } } -> accumulated"},{"name":"foldFrom","comment":" Fold over its elements from an initial accumulator value either\n\n  - `Up` from lowest key to highest\n  - `Down` from highest key to lowest\n\n```\nimport Linear exposing (Direction(..))\nimport Stack\nimport Int.Order\nimport KeySet\n\nKeySet.fromStack intIncreasing\n    (Stack.topBelow 234 [ 345, 543 ])\n    |> KeySet.foldFrom [] Down (::)\n--> [ 234, 345, 543 ]\n\nKeySet.fromStack intIncreasing\n    (Stack.topBelow False [ True, False ])\n    |> KeySet.foldFrom 0 Up (||)\n--> True\n\n-- ↓ and tag should be opaque\nintIncreasing : KeySet.Sorting Int Int { increasing : () }\nintIncreasing =\n    KeySet.sortingKey identity\n        { tag = { increasing = () }\n        , order = Int.Order.increasing\n        }\n```\n\n","type":"accumulated -> Linear.Direction -> (element -> accumulated -> accumulated) -> Emptiable.Emptiable (KeySet.KeySet element tag_) possiblyOrNever_ -> accumulated"},{"name":"foldOnto","comment":" Fold, starting from one end element transformed to the initial accumulation value,\nthen reducing what's accumulated in a given [`Direction`](https://package.elm-lang.org/packages/lue-bird/elm-linear-direction/latest/)\n\n    import Linear exposing (Direction(..))\n    import Stack\n    import Int.Order\n    import KeySet\n\n    KeySet.fromStack intIncreasing\n        (Stack.topBelow 234 [ 345, 543 ])\n        |> KeySet.foldOnto Stack.only Up Stack.onTopLay\n    --> Stack.topBelow 543 [ 345, 234 ]\n    --  the type knows it's never empty\n\n    -- ↓ and tag should be opaque\n    intIncreasing : KeySet.Sorting Int Int { increasing : () }\n    intIncreasing =\n        KeySet.sortingKey identity\n            { tag = { increasing = () }\n            , order = Int.Order.increasing\n            }\n\nA simpler version is [`fold`](#fold)\n\n    KeySet.fold =\n        KeySet.foldOnto identity\n\n","type":"(element -> accumulated) -> Linear.Direction -> (element -> accumulated -> accumulated) -> Emptiable.Emptiable (KeySet.KeySet element tag_) Basics.Never -> accumulated"},{"name":"fromList","comment":" Convert to a [`KeysSet`](#KeySet),\nignoring elements whose keys already exist **earlier** in the `List`\n\nFor construction, use [`fromStack`](#fromStack),\nproving to the compiler what you already know\n\n","type":"KeySet.Sorting element key_ tag -> List.List element -> Emptiable.Emptiable (KeySet.KeySet element tag) Possibly.Possibly"},{"name":"fromStack","comment":" Convert to a [`KeysSet`](#KeySet),\nignoring elements whose keys already exist **earlier** in the [`Stack`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack)\n\n    Keyset.fromStack User.ByHandle\n        (Stack.topBelow\n            { handle = \"cr\", shown = \"chris \\\\o/\" }\n            [ { handle = \"ann\", shown = \"Ann in stand by\" }\n            , -- ↓ won't be part of the KeySet\n              { handle = \"cr\", shown = \"creeper\" }\n            ]\n        )\n\n","type":"KeySet.Sorting element key_ tag -> Emptiable.Emptiable (Stack.Stacked element) possiblyOrNever -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever"},{"name":"insert","comment":" Insert a given element.\nReplaces the element when there is a key collision\n","type":"KeySet.Sorting element key_ tag -> element -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) never_"},{"name":"intersect","comment":" Keep each element whose key also appears in a given [`KeySet`](#KeySet)\n","type":"KeySet.Sorting element key_ tag -> Emptiable.Emptiable (KeySet.KeySet element tag) incomingPossiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) Possibly.Possibly"},{"name":"map","comment":" Change each element based on its current value.\nRuntime `n * log n` because mapped keys could be different (many other dicts/sets have runtime `n`)\n","type":"(element -> mappedElement) -> KeySet.Sorting mappedElement mappedKey_ mappedTag -> Emptiable.Emptiable (KeySet.KeySet element tag_) possiblyOrNever -> Emptiable.Emptiable (KeySet.KeySet mappedElement mappedTag) possiblyOrNever"},{"name":"mapTry","comment":" Try to change each element based on its current value.\nRuntime `n * log n` just like [`KeySet.map`](#map) because mapped keys could be different\n\n    {-| Keep only elements that pass a given test.\n    Often called \"filter\"\n    -}\n    when sorting isGood =\n        KeySet.mapTry\n            (\\element ->\n                if element |> isGood then\n                    Just element\n\n                else\n                    Nothing\n            )\n            sorting\n\n","type":"(element -> Emptiable.Emptiable mappedElement possiblyOrNever) -> KeySet.Sorting mappedElement mappedKey_ mappedTag -> Emptiable.Emptiable (KeySet.KeySet element tag_) possiblyOrNever -> Emptiable.Emptiable (KeySet.KeySet mappedElement mappedTag) Possibly.Possibly"},{"name":"only","comment":" [`KeysSet`](#KeySet) containing a single given element\n","type":"element -> Emptiable.Emptiable (KeySet.KeySet element tag_) never_"},{"name":"size","comment":" Number of elements in the [`KeysSet`](#KeySet).\nRuntime `1`\n\n    KeySet.only \"Hello\"\n        |> KeySet.size\n    --> 1\n\n","type":"Emptiable.Emptiable (KeySet.KeySet element_ tag_) possiblyOrNever_ -> Basics.Int"},{"name":"sortingKey","comment":" By which aspect = key and in which key `Order` the elements are [sorted](#Sorting)\n\nFor example, to create a [`Sorting`](#Sorting) to use with a simple set, use\n\n    sortingKey identity ..tag..order..\n\nmore in\n\n  - [`KeySet` example](#KeySet)\n  - [readme example](https://dark.elm.dmy.fr/packages/lue-bird/elm-keysset/latest/#KeySet)\n\n","type":"(element -> key) -> { tag : tag, order : Order.Ordering key } -> KeySet.Sorting element key tag"},{"name":"toList","comment":" Convert to a `List` sorted by keys\nin a given [`Direction`](https://dark.elm.dmy.fr/packages/lue-bird/elm-linear-direction/latest/Linear#Direction)\n\n    import Linear exposing (Direction(..))\n    import Stack\n    import KeySet\n    import Case\n    import Char.Order\n    import String.Order\n\n    -- tag should be opaque in a separate module\n    nameAlphabetical : KeySet.Sorting String String { alphabetical : () }\n    nameAlphabetical =\n        KeySet.sortingKey identity\n            { tag = { alphabetical = () }\n            , order = String.Order.greaterEarlier (Char.Order.alphabetically Case.lowerUpper)\n            }\n\n    KeySet.fromStack nameAlphabetical\n        (Stack.topBelow \"Bob\" [ \"Alice\" ])\n        |> KeySet.toList Up\n    --> [ \"Alice\", \"Bob\" ]\n\n    KeySet.fromStack nameAlphabetical\n        (Stack.topBelow \"Bob\" [ \"Alice\" ])\n        |> KeySet.toList Down\n    --> [ \"Bob\", \"Alice\" ]\n\n","type":"Linear.Direction -> Emptiable.Emptiable (KeySet.KeySet element tag_) possiblyOrNever_ -> List.List element"},{"name":"unifyWith","comment":" Combine with another [`KeySet`](#KeySet).\nOn key collision, keep the current [`KeySet`](#KeySet)'s element\n","type":"KeySet.Sorting element key_ tag -> Emptiable.Emptiable (KeySet.KeySet element tag) incomingPossiblyOrNever_ -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever -> Emptiable.Emptiable (KeySet.KeySet element tag) possiblyOrNever"}],"binops":[]},{"name":"KeysSet","comment":"\n\n@docs KeysSet\n\n\n## create\n\n@docs promising\n\n\n### unique or not?\n\n@docs Uniqueness, unique\n\n\n## scan\n\n@docs isEqualTo, isEmpty, element, size, isUniqueIn, all, any\n@docs uniqueness\n\n\n## altering\n\n@docs insert, insertList, elementRemove, elementAlter, alter\n@docs map, mapTry\n\n\n## transform\n\n@docs foldFrom, toList\n\n","unions":[{"name":"KeysSet","comment":" 🦄 Unsorted data structure\nthat lets you specify aspects that are checked to be unique across all elements\n\n    countries : KeysSet { flag : String, code : String, name : String }\n    countries =\n        KeysSet.promising\n            [ unique .flag, unique .code ]\n            |> KeysSet.insertList\n                [ { flag = \"🇦🇺\", code = \"AU\", name = \"Australia\" }\n                , { flag = \"🇦🇶\", code = \"AQ\", name = \"Antarctica\" }\n                , { flag = \"🇱🇧\", code = \"LB\", name = \"Lebanon\" }\n                ]\n\n    -- aspect to check for matches + key → matching element\n    countries |> KeysSet.element ( .flag, \"🇦🇶\" )\n    --> Just { flag = \"🇦🇶\", code = \"AQ\", name = \"Antarctica\" }\n\n    countries |> KeysSet.element ( .code, \"LB\" )\n    --> Just { flag = \"🇱🇧\", code = \"LB\", name = \"Lebanon\" }\n\n","args":["element"],"cases":[]}],"aliases":[{"name":"Uniqueness","comment":" A check on whether 2 values are equal in some aspect.\nSee [`unique`](#unique)\n\n    uniqueInCasedLetter =\n        [ unique .inAlphabet\n        , unique .lowercase\n        , unique .uppercase\n        ]\n\n    KeysSet.promising uniqueInCasedLetter\n        |> KeysSet.insert\n            { inAlphabet = 0, lowercase = 'a', uppercase = 'A' }\n        |> KeysSet.insert\n            { inAlphabet = 0, lowercase = 'b', uppercase = 'B' }\n        -- not inserted\n        -- There's already an element where .inAlphabet is 0\n\n","args":["value"],"type":"value -> value -> { areUnique : Basics.Bool }"}],"values":[{"name":"all","comment":" Whether all elements pass a given test.\n\n    KeysSet.promising\n        [ unique .username, unique .email ]\n        |> KeysSet.insertList\n            [ { username = \"fred\", priority = 1, email = \"higgi@outlook.com\" }\n            , { username = \"gria\", priority = 3, email = \"miggo@inlook.go\" }\n            ]\n        |> KeysSet.all (\\user -> user.priority < 4)\n    --> True\n\n","type":"(element -> Basics.Bool) -> KeysSet.KeysSet element -> Basics.Bool"},{"name":"alter","comment":" Change every element based on its current value\n\n    rankUpAllUsers =\n        KeysSet.updateAll\n            (\\user -> { user | rank = user.rank + 1 })\n\nIf aspects that are promised to be unique become the same for 2 elements,\nthe more recently inserted element is chosen\n\nYour function changes the type of the element? → [`KeysSet.map`](#map)\n\nruntime: `length^2`\n\n","type":"(element -> element) -> KeysSet.KeysSet element -> KeysSet.KeysSet element"},{"name":"any","comment":" Whether there are least some elements that pass a given test.\n\n    KeysSet.promising\n        [ unique .username, unique .email ]\n        |> KeysSet.insertList\n            [ { username = \"fred\", priority = 1, email = \"higgi@outlook.com\" }\n            , { username = \"gria\", priority = 3, email = \"miggo@inlook.go\" }\n            ]\n        |> KeysSet.any (\\user -> user.priority > 4)\n    --> False\n\n    member needle =\n        KeysSet.any ((==) needle)\n\n","type":"(element -> Basics.Bool) -> KeysSet.KeysSet element -> Basics.Bool"},{"name":"element","comment":" Try to find an element where a given aspect matches a given value\n\n    casedLetters =\n        KeysSet.promising\n            [ unique .lowercase, unique .uppercase ]\n            |> KeysSet.insertList\n                [ { lowercase = 'a', uppercase = 'A' }\n                , { lowercase = 'b', uppercase = 'B' }\n                ]\n\n    lowercase char =\n        casedLetters\n            |> KeysSet.element .uppercase char\n            |> Maybe.map .lowercase\n\n    uppercase char =\n        casedLetters\n            |> KeysSet.element .lowercase char\n            |> Maybe.map .uppercase\n\nIf the given aspect isn't promised to be unique,\n`at` will find the most recently inserted element where the given aspect matches the given value\n\n    ratedOperators : KeysSet { rating : Float, symbol : String, name : String }\n    ratedOperators =\n        KeysSet.promising\n            [ unique .symbol, unique .name ]\n            |> KeysSet.insertList\n                [ { rating = 0.5, symbol = \"<\", name = \"lt\" }\n                , { rating = 0.5, symbol = \">\", name = \"gt\" }\n                ]\n\n    ratedOperators\n        |> KeysSet.element ( .rating, 0.5 )\n    --> { rating = 0.5, symbol = \">\", name = \"gt\" }\n    -->     |> Just\n\nruntime: `length`\n\n","type":"( element -> aspect, aspect ) -> KeysSet.KeysSet element -> Maybe.Maybe element"},{"name":"elementAlter","comment":" Change the element with the matching aspect based on its current value\n\n    KeysSet.promising\n        [ unique .username, unique .email ]\n        |> KeysSet.insertList\n            [ { username = \"fred\", priority = 1, email = \"higgi@outlook.com\" }\n            , { username = \"gria\", priority = 3, email = \"miggo@inlook.go\" }\n            ]\n        |> KeysSet.elementAlter ( .username, \"fred\" )\n            (\\user -> { user | priority = user.priority + 3 })\n        |> KeysSet.isEqualTo\n            (KeysSet.promising [ unique .email ]\n                |> KeysSet.insertList\n                    [ { username = \"fred\", priority = 4, email = \"higgi@outlook.com\" }\n                    , { username = \"gria\", priority = 3, email = \"miggo@inlook.go\" }\n                    ]\n            )\n    --> True\n\nIf this aspect isn't unique, all elements with the matching aspect are altered\n\n    KeysSet.promising [ unique .email ]\n        |> KeysSet.insertList\n            [ { username = \"fred\", priority = 1, email = \"higgi@outlook.com\" }\n            , { username = \"fred\", priority = 3, email = \"miggo@inlook.go\" }\n            ]\n        |> KeysSet.elementAlter ( .username, \"fred\" )\n            (\\user -> { user | priority = user.priority + 3 })\n        |> KeysSet.isEqualTo\n            (KeysSet.promising [ unique .email ]\n                |> KeysSet.insertList\n                    [ { username = \"fred\", priority = 4, email = \"higgi@outlook.com\" }\n                    , { username = \"fred\", priority = 6, email = \"miggo@inlook.go\" }\n                    ]\n            )\n    --> True\n\nTo change all elements → [`map`](#map), [`mapTry`](#mapTry) or [`alter`](#alter) if the result type is the same as before\n\nruntime: `length`\n\n","type":"( element -> aspect, aspect ) -> (element -> element) -> KeysSet.KeysSet element -> KeysSet.KeysSet element"},{"name":"elementRemove","comment":" Remove the element where a given aspect of the element matches a given value\n\n    openClosedBrackets : KeysSet { open : String, closed : String }\n    openClosedBrackets =\n        KeysSet.promising\n            [ unique .open, unique .closed ]\n            |> KeysSet.insert\n                { open = \"(\", closed = \")\" }\n\n    openClosedBrackets\n        |> KeysSet.elementRemove ( .open, \")\" )\n        |> KeysSet.isEmpty\n    --> False\n    -- .open is never \")\"\n\n    openClosedBrackets\n        |> KeysSet.elementRemove ( .closed, \")\" )\n        |> KeysSet.isEmpty\n    --> True\n\nIf the checked aspect isn't promised to be unique, [`elementRemove`](#elementRemove) acts like a filter\n\n    KeysSet.promising\n        [ unique .open, unique .closed ]\n        |> KeysSet.insertList\n            [ { open = \"[\", closed = \"]\", description = \"List\" }\n            , { open = \"<\", closed = \">\", description = \"Custom\" }\n            , { open = \"\\\\\", closed = \"/\", description = \"Custom\" }\n            ]\n        |> KeysSet.elementRemove ( .description, \"Custom\" )\n        |> KeysSet.toList\n    --> [ { open = \"[\", closed = \"]\", description = \"List\" } ]\n\n[`KeysSet.mapTry`](#mapTry) to filter values\n\nruntime: `length`\n\n","type":"( element -> aspect, aspect ) -> KeysSet.KeysSet element -> KeysSet.KeysSet element"},{"name":"foldFrom","comment":" Reduce the elements from most recently to least recently inserted element\n\n> The keys can be non-comparable. There is no obvious order.\n\n> → You shouldn't rely on order when using functions like `fold` or `toList`\n\n    brackets : KeysSet { open : Char, closed : Char }\n    brackets =\n        KeysSet.promising\n            [ unique .open, unique .closed ]\n            |> KeysSet.insertList\n                [ { open = '(', closed = ')' }\n                , { open = '{', closed = '}' }\n                ]\n\n    brackets\n        |> KeysSet.foldFrom []\n            (\\{ open, closed } ->\n                (::) (String.fromList [ open, closed ])\n            )\n    --> []\n    -->     |> (::) (String.fromList [ '{', '}' ])\n    -->     |> (::) (String.fromList [ '(', ')' ])\n\n","type":"accumulationValue -> (element -> accumulationValue -> accumulationValue) -> KeysSet.KeysSet element -> accumulationValue"},{"name":"insert","comment":" Put an element into the `KeysSet`.\n\nIf there is already an element where some aspect that is promised to be unique is equal\n(see [`Uniqueness`](#Uniqueness)),\nthe [`KeysSet`](#KeysSet) remains **unchanged**\n\n    KeysSet.promising\n        [ unique .lowercase, unique .uppercase ]\n        |> KeysSet.insert\n            { lowercase = 'b', uppercase = 'B', rating = 0.5 }\n            -- is inserted\n        |> KeysSet.insert\n            { lowercase = 'a', uppercase = 'A', rating = 0.5 }\n            -- is inserted\n            -- .rating is not specified as unique\n        |> KeysSet.insert\n            { lowercase = 'b', uppercase = 'C', rating = 0 }\n            -- is ignored\n            -- .lowercase 'b' already exists\n        |> KeysSet.insert\n            { lowercase = 'c', uppercase = 'A', rating = 0 }\n            -- is ignored\n            -- .uppercase 'A' already exists\n        |> KeysSet.insert\n            { lowercase = 'c', uppercase = 'C', rating = 0.6 }\n            -- is inserted\n        |> KeysSet.isEqualTo\n            (KeysSet.promising\n                [ unique .lowercase, unique .uppercase ]\n                |> KeysSet.insertList\n                    [ { lowercase = 'b', uppercase = 'B', rating = 0.5 }\n                    , { lowercase = 'a', uppercase = 'A', rating = 0.5 }\n                    , { lowercase = 'c', uppercase = 'C', rating = 0.6 }\n                    ]\n            )\n    --> True\n\nruntime: `length`\n\n","type":"element -> KeysSet.KeysSet element -> KeysSet.KeysSet element"},{"name":"insertList","comment":" Conveniently [`insert`](#insert) a `List` of elements\n\n    KeysSet.promising\n        [ unique .open, unique .closed ]\n        |> KeysSet.insertList\n            [ { open = '(', closed = ')' }\n            , { open = '{', closed = '}' }\n            ]\n        |> KeysSet.isEqualTo\n            (KeysSet.promising [ unique .open, unique .closed ]\n                |> KeysSet.insert { open = '(', closed = ')' }\n                |> KeysSet.insert { open = '{', closed = '}' }\n            )\n    --> True\n\nruntime: `setLength * listLength`\n\n","type":"List.List element -> KeysSet.KeysSet element -> KeysSet.KeysSet element"},{"name":"isEmpty","comment":" Whether there are no elements inside\n\n    KeysSet.promising [ unique .name ]\n        |> KeysSet.isEmpty\n    --> True\n\n    KeysSet.promising [ unique .name ]\n        |> KeysSet.insertList []\n        |> KeysSet.isEmpty\n    --> True\n\n    KeysSet.promising [ unique .name ]\n        |> KeysSet.insert { name = \"pete\" }\n        |> KeysSet.isEmpty\n    --> False\n\n","type":"KeysSet.KeysSet element_ -> Basics.Bool"},{"name":"isEqualTo","comment":" How can you know if each element in `aKeysSet` can also be found in `bKeysSet`?\n\n    letterCodes : KeysSet { letter : Char, code : Int }\n    letterCodes =\n        KeysSet.insertList\n            [ { letter = 'a', code = 97 }\n            , { letter = 'b', code = 98 }\n            ]\n            (KeysSet.promising\n                [ unique .letter, unique .code ]\n            )\n\n    fancyCompetingLetterCodes : KeysSet { letter : Char, code : Int }\n    fancyCompetingLetterCodes =\n        KeysSet.promising\n            [ unique .code, unique .letter ]\n            |> KeysSet.insert { code = 98, letter = 'b' }\n            |> KeysSet.insert { code = 97, letter = 'a' }\n\n    letterCodes == fancyCompetingLetterCodes\n    -- elm crashes\n    -- because a `KeysSet`'s `Uniqueness` is defined as functions\n\n    (letterCodes |> KeysSet.toList)\n        == (fancyCompetingLetterCodes |> KeysSet.toList)\n    -- both contain the same elements\n    -- but in a different order\n    --> False\n\n    letterCodes\n        |> KeysSet.isEqualTo fancyCompetingLetterCodes\n    --> True\n\n> → Don't use `==` to compare `KeysSet`s\n\n> The keys can be non-comparable. There is no obvious order.\n> → You shouldn't rely on order when using functions like `fold` or `toList`\n\nruntime: `length^2`\n\n","type":"KeysSet.KeysSet element -> KeysSet.KeysSet element -> Basics.Bool"},{"name":"isUniqueIn","comment":" Whether this element is considered unique / would be [`insert`](#insert)ed\n\n    letters : KeysSet { lowercase : Char, uppercase : Char }\n    letters =\n        KeysSet.promising\n            [ unique .lowercase, unique .uppercase ]\n            |> KeysSet.insertList\n                [ { lowercase = 'a', uppercase = 'A' }\n                , { lowercase = 'b', uppercase = 'B' }\n                ]\n\n    KeysSet.isUniqueIn letters\n        { lowercase = 'b', uppercase = 'C' }\n    -- .lowercase 'b' already exists\n    --> False\n\n    KeysSet.isUniqueIn letters\n        { lowercase = 'c', uppercase = 'A' }\n    -- .uppercase 'A' already exists\n    --> False\n\n    KeysSet.isUniqueIn letters\n        { lowercase = 'c', uppercase = 'C' }\n    --> True\n\nruntime: `length`\n\n","type":"KeysSet.KeysSet element -> element -> Basics.Bool"},{"name":"map","comment":" Alter every element based on its current value\n\n    digitNames =\n        KeysSet.promising\n            [ unique .number, unique .name ]\n            |> KeysSet.insertList\n                [ { number = 0, name = \"zero\" }\n                , { number = 1, name = \"one\" }\n                ]\n\n    mathSymbolNames =\n        digitNames\n            |> KeysSet.map\n                (\\{ number, name } ->\n                    { symbol = String.fromInt number, name = name }\n                )\n                [ unique .symbol, unique .name ]\n            |> KeysSet.insert { symbol = \"+\", name = \"plus\" }\n\nYour function doesn't change the type of the element? → [`KeysSet.alter`](#alter)\n\nruntime: `length^2`\n\n","type":"(element -> mappedElement) -> List.List (KeysSet.Uniqueness mappedElement) -> KeysSet.KeysSet element -> KeysSet.KeysSet mappedElement"},{"name":"mapTry","comment":" Only keep elements that are transformed to `Just` by a given function\n\n    operators : KeysSet { symbol : String, name : String }\n    operators =\n        KeysSet.promising\n            [ unique .symbol, unique .name ]\n            |> KeysSet.insertList\n                [ { symbol = \">\", name = \"gt\" }\n                , { symbol = \"<\", name = \"lt\" }\n                , { symbol = \"==\", name = \"eq\" }\n                ]\n\n    -- singleCharOperators\n    operators\n        |> KeysSet.mapTry\n            (\\operator ->\n                case operator.symbol |> String.length of\n                    1 ->\n                        operator.name |> Just\n                    _ ->\n                        Nothing\n            )\n            [ unique identity ]\n        |> KeysSet.toList\n    --> [ \"gt\", \"lt\" ]\n\nruntime: `length^2`\n\n","type":"(element -> Maybe.Maybe mappedElementFill) -> List.List (KeysSet.Uniqueness mappedElementFill) -> KeysSet.KeysSet element -> KeysSet.KeysSet mappedElementFill"},{"name":"promising","comment":" A `KeysSet` with no elements inside,\npromising that given aspects are unique across all elements.\nSee [`Uniqueness`](#Uniqueness)\n\n    KeysSet.promising [ unique .email ]\n        |> KeysSet.insert\n            { username = \"ben\", email = \"ben10@gmx.de\" }\n        |> KeysSet.insert\n            { username = \"mai\", email = \"ben10@gmx.de\" }\n        -- not inserted\n        -- There's already an element where .email is \"ben10@gmx.de\"\n\nElements that are inserted must **not** contain **functions, json or regexes**.\nElm will crash trying to see if they are equal\n\n","type":"List.List (KeysSet.Uniqueness element) -> KeysSet.KeysSet element"},{"name":"size","comment":" How many elements there are\n\n    KeysSet.promising [ unique identity ]\n        |> KeysSet.insertList (List.range 0 41)\n        |> KeysSet.size\n    --> 42\n\n","type":"KeysSet.KeysSet element_ -> Basics.Int"},{"name":"toList","comment":" The `List` containing all elements from most recently (= head) to least recently inserted element\n\n> The keys can be non-comparable. There is no obvious order.\n\n> → You shouldn't rely on order when using functions like `fold` or `toList`\n\n    mostRecentlyInserted =\n        KeysSet.toList >> List.head\n\n    KeysSet.promising\n        [ unique .open, unique .closed ]\n        |> KeysSet.insertList\n            [ { open = '(', closed = ')' }\n            , { open = '{', closed = '}' }\n            ]\n        |> KeysSet.toList\n    --> [ { open = '{', closed = '}' }\n    --> , { open = '(', closed = ')' }\n    --> ]\n\nruntime: `1`\n\n","type":"KeysSet.KeysSet element -> List.List element"},{"name":"unique","comment":" Check values on whether a given aspect is the same structurally\n\n    unique .name\n        { name = \"smile\", symbol = '😊' }\n        { symbol = '🙂', name = \"smile\" }\n    --> { areUnique = False }\n\n    unique .symbol\n        { name = \"smile\", symbol = '😊' }\n        { symbol = '🙂', name = \"smile\" }\n    --> { areUnique = True }\n\n    unique (\\person -> ( person.firstName, person.lastName ))\n        { lastName = \"jimmy\", firstName = \"petter\" }\n        { lastName = \"jimmy\", firstName = \"greg\" }\n    --> { areUnique = True }\n\nin `KeysSet`\n\n    KeysSet.promising [ unique .email ]\n        |> KeysSet.insert\n            { username = \"ben\", email = \"ben10@gmx.de\" }\n        |> KeysSet.insert\n            { username = \"mai\", email = \"ben10@gmx.de\" }\n        -- not inserted\n        -- There's already an element where .email is \"ben10@gmx.de\"\n\n","type":"(value -> aspectToCheckForStructuralEquality_) -> KeysSet.Uniqueness value"},{"name":"uniqueness","comment":" What [`Uniqueness`](#Uniqueness) the [`KeysSet`](#KeysSet) is [`promising`](#promising)\nto check for.\n\n    KeysSet.promising [ unique .open, unique .closed ]\n        |> KeysSet.uniqueness\n    --→ [ unique .open, unique .closed ]\n\nThis is rarely useful! Some examples:\n\n    alter change =\n        \\keysSet ->\n            keysSet |> KeysSet.map change (keysSet |> uniqueness)\n\n    where isOk =\n        \\keysSet ->\n            keysSet\n                |> KeysSet.mapTry\n                    (\\element ->\n                        if element |> isOk then\n                            element |> Just\n\n                        else\n                            Nothing\n                    )\n                    (keysSet |> uniqueness)\n\n","type":"KeysSet.KeysSet element -> List.List (KeysSet.Uniqueness element)"}],"binops":[]}]