[{"name":"AToZ","comment":" Basic latin letter a|...|z. See also [`AToZ.Morph`](AToZ-Morph)\n\n@docs AToZ, Case\n\n","unions":[{"name":"AToZ","comment":" Basic latin letter without [case](#Case) information\n","args":[],"cases":[["A",[]],["B",[]],["C",[]],["D",[]],["E",[]],["F",[]],["G",[]],["H",[]],["I",[]],["J",[]],["K",[]],["L",[]],["M",[]],["N",[]],["O",[]],["P",[]],["Q",[]],["R",[]],["S",[]],["T",[]],["U",[]],["V",[]],["W",[]],["X",[]],["Y",[]],["Z",[]]]},{"name":"Case","comment":" Either lower or upper case\n","args":[],"cases":[["CaseLower",[]],["CaseUpper",[]]]}],"aliases":[],"values":[],"binops":[]},{"name":"AToZ.Morph","comment":" [`Morph`](Morph#Morph) for a [basic latin letter a|...|z](AToZ#AToZ)\n\n\n## [`Morph`](Morph#Morph)\n\n@docs only, broadCase\n@docs lowerChar, upperChar, char\n\n","unions":[],"aliases":[],"values":[{"name":"broadCase","comment":" [`Morph`](Morph#Morph) that when calling [`toBroad`](Morph#toBroad) always returns a letter with a given [`Case`](AToZ#Case).\n\nFor any more complex [`toBroad`](Morph#toBroad) process, use [`oneToOne`](Morph#oneToOne)\n\nFor the general idea, check out [`Morph.broad`](Morph#broad)\n\nExample: We want to format it as lowercase but also accept uppercase:\n\n    AToZ.broadCase AToZ.CaseLower\n        |> Morph.over AToZ.Morph.char\n\nwhich would be equivalent to\n\n    Morph.oneToOne .letter (\\letter -> { letter = letter, case_ = AToZ.CaseLower })\n        |> Morph.over AToZ.Morph.char\n\n","type":"AToZ.Case -> Morph.Morph AToZ.AToZ { case_ : AToZ.Case, letter : AToZ.AToZ }"},{"name":"char","comment":" Morph a letter [`AToZ`](AToZ#AToZ) and its [`Case`](AToZ#Case)\nfrom a `Char`\n\n> ℹ️ Equivalent regular expression: `[a-zA-Z]`\n\n    import AToZ\n\n    -- match any letter, remembering the case\n    'a' |> Morph.toNarrow AToZ.Morph.char\n    --> Ok { case_ = AToZ.CaseLower, letter = AToZ.A }\n\n    'A' |> Morph.toNarrow AToZ.Morph.char\n    --> Ok { case_ = AToZ.CaseUpper, letter = AToZ.A }\n\n    -- digits, symbols etc makes it fail\n    '1'\n        |> Morph.toNarrow AToZ.Morph.char\n        |> Result.toMaybe\n    --> Nothing\n\nCombine with [`broadCase`](#broadCase) to provide a default casing on [`toBroad`](Morph#toBroad)\n\nCombine with [`Morph.one`](Morph#one) to use it in a [`MorphRow`](Morph#MorphRow)\n\n\n### example `Morph.whilePossible (AToZ.Morph.char |> Morph.one)`\n\n> ℹ️ Equivalent regular expression: `[a-zA-Z]*`\n\n    import Morph\n    import List.Morph\n\n    -- multiple letters, remembering their cases\n    \"aBc\"\n        |> Morph.toNarrow\n            (Morph.whilePossible (AToZ.Morph.char |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok\n    -->     [ { case_ = AToZ.CaseLower, letter = AToZ.A }\n    -->     , { case_ = AToZ.CaseUpper, letter = AToZ.B }\n    -->     , { case_ = AToZ.CaseLower, letter = AToZ.C }\n    -->     ]\n\n    -- greek letters, space, -, ', . etc are not [a-Z]\n    \"abπc\"\n        |> Morph.toNarrow\n            (Morph.broad []\n                |> Morph.overRow\n                    (Morph.whilePossible (AToZ.Morph.char |> Morph.one))\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"Morph.Morph { case_ : AToZ.Case, letter : AToZ.AToZ } Char.Char"},{"name":"lowerChar","comment":" Match a lowercase letter `Char`.\n\n> ℹ️ Equivalent regular expression: `[a-z]`\n\n    import Morph\n    import List.Morph\n    import AToZ exposing (AToZ(..))\n\n    -- match a lowercase letter\n    'a' |> Morph.toNarrow AToZ.Morph.lowerChar\n    --> Ok A\n\n    -- but anything else makes it fail\n    'A'\n        |> Morph.toNarrow AToZ.Morph.lowerChar\n        |> Result.toMaybe\n    --> Nothing\n\nCombine with [`Morph.one`](Morph#one) to use it in a [`MorphRow`](Morph#MorphRow)\n\nThis is different from\n\n    AToZ.Morph.broadCase AToZ.CaseLower\n        |> Morph.over AToZ.Morph.char\n\nwhich parses any case but only prints lowercase\n\n","type":"Morph.Morph AToZ.AToZ Char.Char"},{"name":"only","comment":" Match only the specific given broad input. See [`Morph.only`](Morph#only)\n","type":"AToZ.AToZ -> Morph.Morph () AToZ.AToZ"},{"name":"upperChar","comment":" Match an uppercase letter `Char`.\n\n> ℹ️ Equivalent regular expression: `[A-Z]`\n\n    import Morph\n    import List.Morph\n    import AToZ exposing (AToZ(..))\n\n    -- match an uppercase a-z letter\n    'A' |> Morph.toNarrow AToZ.Morph.upperChar\n    --> Ok A\n\n    -- but anything else makes it fail\n    'a'\n        |> Morph.toNarrow AToZ.Morph.upperChar\n        |> Result.toMaybe\n    --> Nothing\n\nCombine with [`Morph.one`](Morph#one) to use it in a [`MorphRow`](Morph#MorphRow)\n\nThis is different from\n\n    AToZ.Morph.broadCase AToZ.CaseUpper\n        |> Morph.over AToZ.Morph.char\n\nwhich parses any case but only prints uppercase\n\n","type":"Morph.Morph AToZ.AToZ Char.Char"}],"binops":[]},{"name":"Array.Morph","comment":" [`Morph`](Morph) for an [`elm/core` `Array element`](https://dark.elm.dmy.fr/packages/elm/core/latest/Array#Array)\n\n\n## alter\n\n@docs each\n\n\n## transform\n\n@docs list, stack, arraySized, string\n@docs value\n\n","unions":[],"aliases":[],"values":[{"name":"arraySized","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an [`ArraySized`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typesafe-array/latest/)\n\n    import ArraySized\n    import Array\n    import Morph\n\n    ArraySized.l4 0 1 2 3\n        |> Morph.mapTo Array.Morph.arraySized\n    --> Array.fromList [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`ArraySized.Morph.array`](ArraySized-Morph#array)\n\n","type":"Morph.MorphIndependently (ArraySized.ArraySized narrowElement narrowRange_ -> Result.Result error_ (Array.Array narrowElement)) (Array.Array broadElement -> ArraySized.ArraySized broadElement (N.Min (N.Up0 broadX_)))"},{"name":"each","comment":" [`Morph`](Morph#Morph) all elements.\nOn the narrowing side all [narrowed](Morph#toNarrow) values must be `Ok`\nfor it to not result in a [`Morph.Error`](Morph#Error)\n\nIf the element [`Morph`](Morph#Morph) is [`OneToOne`](Morph#OneToOne),\n`each` will always succeed with the type knowing it does\n\n","type":"Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (Array.Array beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) (Array.Array narrow)) (Array.Array beforeToBroad -> Array.Array broad)"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List`\n\n    import Array\n    import Morph\n\n    [ 0, 1, 2, 3 ]\n        |> Morph.mapTo Array.Morph.list\n    --> Array.fromList [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`List.Morph.array`](List-Morph#array)\n\n","type":"Morph.MorphIndependently (List.List narrowElement -> Result.Result error_ (Array.Array narrowElement)) (Array.Array broadElement -> List.List broadElement)"},{"name":"stack","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a [stack](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack)\n\n    import Morph\n    import Array\n    import Stack\n\n    Stack.topBelow 0 [ 1, 2, 3 ]\n        |> Morph.mapTo Array.Morph.stack\n    --> Array.fromList [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`Stack.Morph.array`](Stack-Morph#array)\n\n","type":"Morph.MorphIndependently (Emptiable.Emptiable (Stack.Stacked narrowElement) possiblyOrNever_ -> Result.Result error_ (Array.Array narrowElement)) (Array.Array broadElement -> Emptiable.Emptiable (Stack.Stacked broadElement) Possibly.Possibly)"},{"name":"string","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `String` to `Array Char`\n\n    import Array\n    import Morph\n\n    \"0123\"\n        |> Morph.mapTo Array.Morph.string\n    --> Array.fromList [ '0', '1', '2', '3' ]\n\n[Inverse](Morph#invert) of [`String.Morph.array`](String-Morph#array)\n\n","type":"Morph.MorphOrError (Array.Array Char.Char) String.String error_"},{"name":"value","comment":" `Array` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue element -> Value.Morph.Internal.MorphValue (Array.Array element)"}],"binops":[]},{"name":"ArraySized.Morph","comment":" [`Morph`](Morph) for an [`ArraySized element lengthRange`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typesafe-array/latest/)\n\n\n## alter\n\n@docs each\n\n\n## structure\n\n@docs array, list, stack, string\n\n\n## row\n\n@docs exactly, exactlyWith, atLeast, in_\n@docs sequenceMap, broadSequenceMap\n\n","unions":[],"aliases":[],"values":[{"name":"array","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an `Array`\n\n    import ArraySized\n    import Array\n\n    Array.fromList [ 0, 1, 2, 3 ]\n        |> Morph.mapTo ArraySized.Morph.fromArray\n    --: ArraySized (Min (Up0 x_)) number_\n\n[Inverse](Morph#invert) of [`Array.Morph.arraySized`](Array-Morph#arraySized)\n\n","type":"Morph.MorphIndependently (Array.Array narrowElement -> Result.Result error_ (ArraySized.ArraySized narrowElement (N.Min (N.Up0 narrowX_)))) (ArraySized.ArraySized broadElement broadRange_ -> Array.Array broadElement)"},{"name":"atLeast","comment":" Match a value at least a given number of times\nand return them as an [`ArraySized`](https://package.elm-lang.org/packages/lue-bird/elm-typesafe-array/latest/ArraySized).\n\n> ℹ️ Equivalent regular expression: `{min,}`\n\n    import Morph\n    import List.Morph\n    import AToZ.Morph\n    import AToZ\n    import ArraySized\n    import N exposing (n3)\n\n    -- we want at least three letters, we are okay with more than three\n    \"abcdef\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n3 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B, C, D, E, F ]\n\n    -- but not two, that's sacrilegious\n    \"ab\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n3 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n\n### `atLeast n0`\n\n> ℹ️ Equivalent regular expression: `*`\n\n    import Morph\n    import List.Morph\n    import AToZ.Morph\n    import AToZ exposing (AToZ(..))\n    import ArraySized\n    import N exposing (n0)\n\n    -- We want as many letters as there are.\n    \"abc\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n0 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B, C ]\n\n    -- even zero letters is okay\n    \"\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n0 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok []\n\nAs you can see, `atLeast n0` will never fail.\n\nIf you want a to morph a `List` instead of an `ArraySized ... (Min (On N0))`,\nyou might as well use [`Morph.whilePossible`](Morph#whilePossible) instead of\n\n    ArraySized.toList\n        |> Morph.overRow (ArraySized.Morph.atLeast n0)\n\n\n### `atLeast n1`\n\n> ℹ️ Equivalent regular expression: `+`\n\n    import Morph\n    import List.Morph\n    import AToZ.Morph\n    import AToZ exposing (AToZ(..))\n    import ArraySized\n    import N exposing (n1)\n\n    -- we want as many letters as there are\n    \"abc\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n1 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B, C ]\n\n    -- but we want at least one\n    \"\"\n        |> Morph.toNarrow\n            (ArraySized.Morph.atLeast n1 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n\n### example: interspersed separators\n\n    import Stack\n    import Morph\n    import ArraySized.Morph exposing (atLeast)\n    import List.Morph\n    import AToZ.Morph\n    import AToZ exposing (AToZ(..))\n    import N exposing (n0)\n\n\n    tag =\n        atLeast n1 (AToZ.Morph.lowerChar |> Morph.one)\n\n    tags =\n        Morph.narrow Stack.onTopLay\n            |> grab Stack.top tag\n            |> grab Stack.removeTop\n                (List.Morph.arraySized\n                    |> Morph.overRow\n                        (atLeast n0\n                            (Morph.narrow (\\tag -> tag)\n                                |> match separator\n                                |> grab (\\tag -> tag) tag\n                            )\n                        )\n                )\n\n    \"a,bc,def\"\n        |> Morph.toNarrow (tags |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.map (Stack.map (\\_ -> ArraySized.toList))\n    --→ Ok\n    --→     (Stack.topBelow [ A ]\n    --→         [ [ B, C ]\n    --→         , [ D, E, F ]\n    --→         ]\n    --→     )\n\n\n### anti-example: parsing infinitely\n\n    Morph.narrow ...\n        |> grab ... (atLeast n0 (Morph.keep |> Morph.one))\n        |> grab ...\n\nwould only parse the first part until the end\nbecause it always [`narrow`](Morph#narrow)s.\nNothing after would ever be parsed, making the whole thing fail.\n\n\n### minimum type explanation\n\nThe maximum of the lower limit argument enables what's shown in the following example:\n\"match any number of spaces and broaden to 1\"\n\n    broad (ArraySized.one ())\n        |> Morph.overRow (atLeast n0 (String.Morph.only \" \"))\n\nIn this case, the minimum of the given \"seed\" before broadening `ArraySized.one ()` is 1,\nwhereas the narrow result of `atLeast n0` will have a minimum length of 0.\n\nThe maximum of the lower limit argument is a type-level proof that the \"seed\" minimum is greater\nor equal to the resulting narrow minimum length.\n\n↓ for example will lead to a compile time error:\n\n    broad ArraySized.empty\n        |> Morph.overRow (atLeast n1 (String.Morph.only \" \"))\n\n> The argument to `|>` is of type:\n>\n>     ... ArraySized () (In #(On N0)# (Up0 maxX_)) ...\n>\n> But it needs to be:\n>\n>     ... ArraySized () (In #(On N1)# (Up0 maxX_)) ...\n\n","type":"N.N (N.In (N.On lowerLimit) (N.Up lowerLimitToBroad_ N.To broadLowerLimit)) -> Morph.MorphRowIndependently narrow beforeToBroad broadElement -> Morph.MorphRowIndependently (ArraySized.ArraySized narrow (N.Min (N.On lowerLimit))) (ArraySized.ArraySized beforeToBroad (N.In (N.On broadLowerLimit) max_)) broadElement"},{"name":"broadSequenceMap","comment":" Match broad [`MorphRow`](Morph#MorphRow)s\n(those that can always produce the same broad value)\nbased on given input elements in sequence.\n\nMore details → [`List.Morph.broadSequenceMap`](List-Morph#broadSequenceMap)\n\n","type":"(element -> Morph.MorphRow () broadElement) -> ArraySized.ArraySized element (N.In (N.On min_) (N.On max_)) -> Morph.MorphRow () broadElement"},{"name":"each","comment":" Morph each element in an `ArraySized`\n","type":"Morph.MorphIndependently (narrowBeforeMap -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrowMapped) (broadBeforeUnmap -> broadUnmapped) -> Morph.MorphIndependently (ArraySized.ArraySized narrowBeforeMap (N.In narrowMin narrowMax) -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) (ArraySized.ArraySized narrowMapped (N.In narrowMin narrowMax))) (ArraySized.ArraySized broadBeforeUnmap broadRange -> ArraySized.ArraySized broadUnmapped broadRange)"},{"name":"exactly","comment":" Match a value a given number of times\nand return them as an [`ArraySized`](https://package.elm-lang.org/packages/lue-bird/elm-typesafe-array/latest/ArraySized)\n\n> ℹ️ Equivalent regular expression: `{n}`\n\n    import Morph\n    import Char.Morph\n    import String.Morph\n    import AToZ exposing (AToZ(..))\n    import AToZ.Morph\n    import N exposing (n3)\n    import ArraySized\n    import List.Morph\n\n    -- we want `exactly 3` letters\n    \"abc\"\n        |> Morph.toNarrow\n            (exactly n3 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B, C ]\n\n    -- not 2 or 4, we want 3\n    \"ab\"\n        |> Morph.toNarrow\n            (exactly n3 (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"N.N (N.In min max) -> Morph.MorphRowIndependently elementBeforeToBroad elementNarrow broadElement -> Morph.MorphRowIndependently (ArraySized.ArraySized elementBeforeToBroad (N.In min max)) (ArraySized.ArraySized elementNarrow (N.In min max)) broadElement"},{"name":"exactlyWith","comment":" Depending on the number parsed by a given morph,\nmorph exactly that amount of elements.\n\nTo for example morph string bits\nwhere the first 16 bits represent the amount of code points that follow:\n\n    ArraySized.Morph.exactlyWith\n        (N.Morph.natural |> Morph.overRow (Natural.Morph.bits n16 Bytes.BE))\n        Char.Morph.bits\n\nThe name is pretty horrible, so suggestions are welcome!\n\nIf you need to parse a format like\n\n    [ length ] [ other necessary data you want to grab ] [ elements ]\n\nPlease open an issue and I'll add a version for it.\nThis isn't exposed currently because the API for this would be jAnKy and the use-case kinda obscure.\n\n\n#### 🐦 Developer's note: Why there is no generic version like\n\n    using :\n        (complete -> toDecide)\n        -> MorphRow toDecide broadElement\n        -> (toDecide -> MorphRow complete broadElement)\n        -> MorphRow complete broadElement\n\nThis might look like the happy \"andThen\" that you love\nbut it's more evil than that!\n\nFor example, you'd typically use \"andThen\" for versioning etc. – not with morphs.\nUse [`Morph.choice`](Morph#choice) where each possibility expects a specific number.\n\n`using` is only unavoidable\nwhen certain data that tells you how to proceed can have infinite possibilities.\n\nHere's some ugly consequences if we use `using` instead of a less generic `exactlyWith`:\n\n  - Its [`description`](Morph#description) can barely tell users anything,\n    as our main morph is hidden behind a function :(\n\n    Adding [`Morph.named`](Morph#named) to the whole `using` morph helps but the quality is still notably lower.\n\n  - Instead of recursively using `using`, you should use\n    [`untilNext`](Morph#untilNext), [`untilLast`](Morph#untilNext), [`untilNextFold`](Morph#untilNextFold), [`untilLastFold`](Morph#untilLastFold)\n    to not blow the stack and get a nicer [`description`](Morph#description)\n\n  - Its harder to reason about\n\n  - It's less composable / less \"independent\"\n\n  - It's easier than ever to get your [`toBroad`](Morph#toBroad) and [`toNarrow`](Morph#toNarrow)\n    functions out of sync\n\n","type":"Morph.MorphRow (N.N range) broadElement -> Morph.MorphRowIndependently elementNarrow elementBeforeToBroad broadElement -> Morph.MorphRowIndependently (ArraySized.ArraySized elementNarrow range) (ArraySized.ArraySized elementBeforeToBroad range) broadElement"},{"name":"in_","comment":" Match a value between a minimum and maximum number of times\nand return them as an [`ArraySized`](https://package.elm-lang.org/packages/lue-bird/elm-typesafe-array/latest/ArraySized).\n\n> ℹ️ Equivalent regular expression: `{min,max}`\n\n    import Morph\n    import AToZ.Morph\n    import AToZ exposing (AToZ(..))\n    import List.Morph\n    import ArraySized\n    import N exposing (n2, n4)\n\n    -- we want between two and four letters\n    \"abc\"\n        |> Morph.toNarrow\n            (in_ ( n2, n4 ) (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B, C ]\n\n\n    \"a\"\n        |> Morph.toNarrow\n            (in_ ( n2, n4 ) (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n\n### `in_ ( n0, n1 )`\n\nAlternative to [`Maybe.Morph.row`](Maybe-Morph#row) which instead returns an `ArraySized`.\n\n> ℹ️ Equivalent regular expression: `?`\n\n\n### example: at most\n\n> ℹ️ Equivalent regular expression: `{0,max}`\n\n    import Morph\n    import AToZ exposing (AToZ(..))\n    import AToZ.Morph\n    import List.Morph\n    import ArraySized\n    import N exposing (n0, n3)\n\n    -- we want a maximum of three letters\n    \"ab\"\n        |> Morph.toNarrow\n            (in_ ( n0, n3 ) (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok [ A, B ]\n\n    -- even zero letters are fine\n    \"\"\n        |> Morph.toNarrow\n            (in_ ( n0, n3 ) (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.map ArraySized.toList\n    --> Ok []\n\n","type":"( N.N (N.In min (N.Up minToMaxMin_ N.To maxMin)), N.N (N.In (N.On maxMin) max) ) -> Morph.MorphRow element broadElement -> Morph.MorphRow (ArraySized.ArraySized element (N.In min max)) broadElement"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List`\n\n    import ArraySized\n    import Morph\n\n    [ 0, 1, 2, 3 ]\n        |> Morph.mapTo ArraySized.Morph.list\n    --: ArraySized (Min (Up0 x_)) number_\n\n[Inverse](Morph#invert) of [`List.Morph.arraySized`](List-Morph#arraySized)\n\n","type":"Morph.MorphIndependently (List.List narrowElement -> Result.Result error_ (ArraySized.ArraySized narrowElement (N.Min (N.Up0 narrowX_)))) (ArraySized.ArraySized broadElement broadRange_ -> List.List broadElement)"},{"name":"sequenceMap","comment":" From the elements in a given `ArraySized`,\ncreate [`MorphRow`](Morph#MorphRow)s\nthat will be run in the same order, one after the other.\n\nMore details → [`List.Morph.sequenceMap`](List-Morph#sequenceMap)\n\n","type":"(element -> Morph.MorphRow elementNarrow broadElement) -> ArraySized.ArraySized element (N.In min max) -> Morph.MorphRow (ArraySized.ArraySized elementNarrow (N.In min max)) broadElement"},{"name":"stack","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a [stack](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack)\n\n    import ArraySized\n    import Morph\n    import Stack\n\n    Stack.topBelow 0 [ 1, 2, 3, 4 ]\n        |> Morph.mapTo ArraySized.Morph.stack\n    --: ArraySized (Min (Up1 x_)) number_\n\n[Inverse](Morph#invert) of [`Stack.Morph.arraySized`](Stack-Morph#arraySized)\n\n","type":"Morph.MorphIndependently (Emptiable.Emptiable (Stack.Stacked narrowElement) narrowPossiblyOrNever -> Result.Result error_ (ArraySized.ArraySized narrowElement (N.Min (N.On (N.N0OrAdd1 narrowPossiblyOrNever N.N0))))) (ArraySized.ArraySized broadElement (N.In (N.On (N.N0OrAdd1 broadPossiblyOrNever minFrom1_)) max_) -> Emptiable.Emptiable (Stack.Stacked broadElement) broadPossiblyOrNever)"},{"name":"string","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `String` to `ArraySized ... Char`\n\n    import ArraySized\n    import Morph\n\n    \"0123\"\n        |> Morph.mapTo ArraySized.Morph.string\n    --: ArraySized (Min (Up0 x_)) number_\n\n[Inverse](Morph#invert) of [`String.Morph.arraySized`](String-Morph#arraySized)\n\n","type":"Morph.MorphIndependently (String.String -> Result.Result error_ (ArraySized.ArraySized Char.Char (N.Min (N.Up0 narrowX_)))) (ArraySized.ArraySized Char.Char broadRange_ -> String.String)"}],"binops":[]},{"name":"Bit.Morph","comment":" [`Morph`](Morph#Morph) for a [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)\n\n@docs char, n, only, value\n\n","unions":[],"aliases":[],"values":[{"name":"char","comment":" `'0'` or `'1'`\n","type":"Morph.Morph Bit.Bit Char.Char"},{"name":"n","comment":" `n0` ↔ `O`, `n1` ↔ `I`\n","type":"Morph.MorphIndependently (N.N (N.In min_ (N.Up maxTo1_ N.To N.N1)) -> Result.Result error_ Bit.Bit) (Bit.Bit -> N.N (N.In (N.Up0 minX_) (N.Up1 maxX_)))"},{"name":"only","comment":" Match a specific given `Bit` and not the other one.\n\n    import Morph\n    import Bit\n\n    Bit.O |> Morph.toNarrow (Bit.Morph.only Bit.I)\n    --> Err (Morph.DeadEnd \"0\")\n\n","type":"Bit.Bit -> Morph.Morph () Bit.Bit"},{"name":"value","comment":" [`MorphValue`](Value-Morph#MorphValue) from a [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)\n","type":"Value.Morph.Internal.MorphValue Bit.Bit"}],"binops":[]},{"name":"Char.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `Char`](https://dark.elm.dmy.fr/packages/elm/core/latest/Char#Char)\n\n@docs only\n@docs code, string, value\n@docs bits\n\n","unions":[],"aliases":[],"values":[{"name":"bits","comment":" [`MorphRow`](Morph#MorphRow) from [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)s.\n\nNote that a `Char` isn't equivalent to a visual unit like 🇨🇿 or 🦸🏽‍♂️ or ả̴̫̼̫̀̅\n(→ see [grapheme](https://dark.elm.dmy.fr/packages/BrianHicks/elm-string-graphemes/latest/)).\nInstead, it's just one UTF-8 code point.\n\n","type":"Morph.MorphRow Char.Char Bit.Bit"},{"name":"code","comment":" Character by unicode [code point](https://en.wikipedia.org/wiki/Code_point)\n\n    import Morph\n\n    Morph.toNarrow Char.Morph.code 65 --> Ok 'A'\n\n    Morph.toNarrow Char.Morph.code 66 --> Ok 'B'\n\n    Morph.toNarrow Char.Morph.code 0x6728 --> Ok '木'\n\n    Morph.toNarrow Char.Morph.code 0x0001D306 --> Ok '𝌆'\n\n    Morph.toNarrow Char.Morph.code 0x0001F603 --> Ok '😃'\n\n    Morph.toNarrow Char.Morph.code -1\n    --> Err (Morph.DeadEnd \"unicode code point outside of range 0 to 0x10FFFF\")\n\nThe full range of unicode is from `0` to `0x10FFFF`. With numbers outside that\nrange, you'll get an error (unlike `Char.fromCode`).\n\n","type":"Morph.Morph Char.Char Basics.Int"},{"name":"only","comment":" Match only the specific given broad input. See [`Morph.only`](Morph#only)\n","type":"Char.Char -> Morph.Morph () Char.Char"},{"name":"string","comment":" [`Morph`](Morph#Morph) a `String` of length 1 to a `Char`\n\nBe aware, that [special-cased characters as the result of `Char.toUpper`](https://github.com/elm/core/issues/1001)\nare [broadened](Morph#toBroad) as 2 `Char`s in a `String`\nand therefore [narrowing](Morph#toNarrow) to a `Char` will fail.\n\n","type":"Morph.Morph Char.Char String.String"},{"name":"value","comment":" `Char` [`MorphValue`](Value-Morph#MorphValue)\n\nBe aware that [special-cased characters as the result of `Char.toUpper`](https://github.com/elm/core/issues/1001)\nare [broadened](Morph#toBroad) as 2 `Char`s in a [`Value.String`](Value#Value)\nand therefore [narrowing](Morph#toNarrow) to a `Char` will fail.\n\n","type":"Value.Morph.Internal.MorphValue Char.Char"}],"binops":[]},{"name":"Decimal","comment":" Arbitrary-size, safe floating point number\nwith the explicit _option_ of allowing of [exceptions](Decimal#Exception) or not.\nSee also [`Decimal.Morph`](Decimal-Morph)\n\n@docs Decimal, Signed, SignedAbsolute, Fraction, AtLeast1\n@docs Exception\n\n\n## create\n\n@docs fromFloat\n\n\n## alter\n\n@docs ceiling, floor, truncate\n\n\n## transform\n\n@docs toFloat, orExceptionToFloat, exceptionToFloat, exceptionToString\n\nThe type is rarely useful in its current state,\nas the only thing you can do is convert from and to other types.\n\nThis is enough for my use-cases\nbut feel free to PR or open an issue if you'd like to see support\nfor arbitrary-precision arithmetic like addition, multiplication, ...\n\n","unions":[{"name":"Decimal","comment":" A decimal number that can have a floating point\n\nDon't shy away from spinning your own version of this if needed, like\n\n    type FieldException\n        = DivisionByZeroResult\n        | Infinity Sign\n\n    Result FieldException Decimal\n\nSee also [`Decimal.Exception`](Decimal#Exception)\n\n","args":[],"cases":[["N0",[]],["Signed",["Decimal.Signed"]]]},{"name":"Exception","comment":" Non-number calculation result, see also [IEEE 754 number exception states](#Exception)\n\n`Result Exception Decimal` for example is like an [`elm/core` `Float`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#Float)\nexcept\n\n  - [`Exception`](#Exception)s are an explicit case so you can easily extract a [`Decimal`](Decimal#Decimal)\n  - it can have arbitrary decimal points, see [`Decimal`](Decimal#Decimal)\n\n","args":[],"cases":[["NaN",[]],["Infinity",["Sign.Sign"]]]},{"name":"SignedAbsolute","comment":" What comes after its [`Sign`](Sign#Sign)\n","args":[],"cases":[["Fraction",["Decimal.Fraction"]],["AtLeast1",["Decimal.AtLeast1"]]]}],"aliases":[{"name":"AtLeast1","comment":" Absolute value of a signed [`Decimal`](#Decimal) ≥ 1\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { whole : Natural.AtLeast1, fraction : Maybe.Maybe Decimal.Fraction }"},{"name":"Fraction","comment":" _Some_ digits after the decimal point. Can't be none.\n\nNote that \"fraction\" here doesn't mean \"rational number with a numerator and denominator\"\nor \"number in range [0;1]\"\nIt means: the absolute value of a written decimal number without a period, like 0.345 or 0.001\n\nYou think this name can be improved? → issue\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { beforeEnd : List.List (N.N (N.In N.N0 N.N9)), end : N.N (N.In N.N1 N.N9) }"},{"name":"Signed","comment":" Any [`Decimal`](Decimal#Decimal) except `0` is represented this way\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { sign : Sign.Sign, absolute : Decimal.SignedAbsolute }"}],"values":[{"name":"ceiling","comment":" Its nearest greater [`Integer`](Integer#Integer) number\n","type":"Decimal.Decimal -> Integer.Integer"},{"name":"exceptionToFloat","comment":" infinity/NaN represented as a `Float`\n","type":"Decimal.Exception -> Basics.Float"},{"name":"exceptionToString","comment":" Print an [`Exception`](#Exception)\n","type":"Decimal.Exception -> String.String"},{"name":"floor","comment":" Its nearest lower [`Integer`](Integer#Integer) number\n","type":"Decimal.Decimal -> Integer.Integer"},{"name":"fromFloat","comment":" Convert from an [`elm/core` `Float`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#Float).\nDon't be surprised to find more precise representations in [`Decimal`](#Decimal)-land\n\n    -9999.124 |> Decimal.fromFloat\n    --→ Ok with the Decimal representation of\n    --→ 999.1239999999997962731868028640747070312\n\n","type":"Basics.Float -> Result.Result Decimal.Exception Decimal.Decimal"},{"name":"orExceptionToFloat","comment":" NaN, infinity or [`Decimal.toFloat`](#toFloat)\n\nKeep in mind that `Decimal -> Float` can be lossy\nsince `Float` is fixed in bit size while [`Decimal`](Decimal#Decimal) is not\n\n","type":"Result.Result Decimal.Exception Decimal.Decimal -> Basics.Float"},{"name":"toFloat","comment":" Convert to a `Float`\n\nKeep in mind that `DecimalOrException -> Float` can be lossy\nsince `Float` is fixed in bit size while [`Decimal`](Decimal#Decimal) is not\n\n","type":"Decimal.Decimal -> Basics.Float"},{"name":"truncate","comment":" Remove the [`Fraction`](#Fraction) part after the decimal point `.`\nto create an [`Integer`](Integer#Integer)\n","type":"Decimal.Decimal -> Integer.Integer"}],"binops":[]},{"name":"Decimal.Morph","comment":" [`Morph`](Morph#Morph) for an [arbitrary-sized `Decimal`](Decimal#Decimal)\n\n@docs value\n\n\n## row\n\n@docs chars, bitsVariableCount\n\n\n## [`Decimal`](Decimal#Decimal) or [`Exception`](Decimal#Exception)\n\n[`Morph`](Morph#Morph) a [`Decimal`](Decimal#Decimal) where infinities and NaN are possible states\n\n@docs orExceptionValue, exceptionValue\n\n\n## `Float`\n\n@docs orExceptionFloat\n\n","unions":[],"aliases":[],"values":[{"name":"bitsVariableCount","comment":" `MorphRow` from from `Bit`s to a [`Decimal`](Decimal#Decimal)\n","type":"Morph.MorphRow Decimal.Decimal Bit.Bit"},{"name":"chars","comment":" [`MorphRow`](Morph#MorphRow) from chars to a [`Decimal`](Decimal#Decimal) number.\n\n    import Morph\n    import List.Morph\n\n    -- trailing 0s are matched but have no effect\n    \"12.0340000\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --→ Ok with a Decimal representing\n    --→ 12.034\n\n    \"-12.000\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --→ Ok with a Decimal representing\n    --→ -12.0\n\n\n    -- leading floating point is allowed\n\n    \".012\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --→ Ok with a Decimal representing\n    --→ 0.012\n\n    \"-.12\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --→ Ok with a Decimal representing\n    --→ -0.12\n\n    -- fails for integers without a floating point, see the not below\n    \"12\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n    -- but succeeds for integers with a trailing floating point\n    \"12.\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --→ Ok with a Decimal representing\n    --→ 12.0\n\n    -- exponential notation, other letters, symbols etc make it fail\n\n    \".\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n    \"3e10\"\n        |> Morph.toNarrow\n            (Decimal.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\nTo allow integers to parse as decimals as well,\nbuild a [`Morph.choice`](Morph#choice) between\n[`Decimal.Morph.chars`](#chars)\nand [`Integer.Morph.chars`](Integer-Morph#chars)\n\nThe fact that `\"12.\"` parses as 12 might also seem weird to you.\nIf you don't want to allow that,\nyou'll need to spin your own version, taking this implementation as a reference.\nIt's not that scary I swear!\n\n","type":"Morph.MorphRow Decimal.Decimal Char.Char"},{"name":"exceptionValue","comment":" [`MorphValue`](Value-Morph#MorphValue) from an [`Exception`](Decimal#Exception)\n","type":"Value.Morph.Internal.MorphValue Decimal.Exception"},{"name":"orExceptionFloat","comment":" [`Morph`](Morph#Morph)\nan [`elm/core` `Float`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#Float)\nto a [`Result Exception Decimal`](Decimal#Exception)\n\nKeep in mind that `DecimalOrException -> Float` can be lossy\nsince `Float` is fixed in bit size while [`Decimal`](Decimal#Decimal) is not.\n\n[Inverse](Morph#invert) of [`Float.Morph.decimalOrException`](Float-Morph#decimalOrException)\n\nIf you need a narrow [`Decimal`](Decimal#Decimal), not a result, try\n\n    Result.Morph.toOk\n        |> Morph.over Decimal.Morph.orExceptionFloat\n        |> Morph.errorMap (Morph.deadEndMap Decimal.exceptionToString)\n\n","type":"Morph.MorphOrError (Result.Result Decimal.Exception Decimal.Decimal) Basics.Float error_"},{"name":"orExceptionValue","comment":" `Float` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue (Result.Result Decimal.Exception Decimal.Decimal)"},{"name":"value","comment":" [`MorphValue`](Value-Morph#MorphValue) from a [`Decimal`](Decimal#Decimal)\n\nTo get a [`MorphValue`](Value-Morph#MorphValue) from a `Float`,\nuse [`Float.Morph.decimalOrException`](Float-Morph#decimalOrException)\nover [`Decimal.Morph.orExceptionValue`](#orExceptionValue)\n\n","type":"Value.Morph.Internal.MorphValue Decimal.Decimal"}],"binops":[]},{"name":"Dict.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `Dict key value`](https://dark.elm.dmy.fr/packages/elm/core/latest/Dict#Dict)\n\n\n## alter\n\n@docs eachValue\n\n\n## transform\n\n@docs list\n@docs value\n\n","unions":[],"aliases":[],"values":[{"name":"eachValue","comment":" [`Morph.OneToOne`](Morph#OneToOne) each value in a `Dict key value`\n","type":"Morph.MorphIndependently (beforeMapValue -> Result.Result (Morph.ErrorWithDeadEnd Basics.Never) mappedValue) (beforeUnmapValue -> unmappedValue) -> Morph.MorphIndependently (Dict.Dict narrowKey beforeMapValue -> Result.Result error_ (Dict.Dict narrowKey mappedValue)) (Dict.Dict broadKey beforeUnmapValue -> Dict.Dict broadKey unmappedValue)"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List { key : key, value : value }` to a `Dict key value`.\n\n    import Dict\n    import Morph\n\n    [ { key = \"git\", value = \"gud\" }\n    , { key = \"Hi\", value = \"there\" }\n    ]\n        |> Morph.mapTo Dict.Morph.list\n    --> Dict.fromList [ ( \"Hi\", \"there\" ), ( \"git\", \"gud\" ) ]\n\n[Inverse](Morph#invert) of [`List.Morph.dict`](List-Morph#dict)\n\n","type":"Morph.MorphIndependently (List.List { key : comparableNarrowKey, value : narrowValue } -> Result.Result error_ (Dict.Dict comparableNarrowKey narrowValue)) (Dict.Dict broadKey broadValue -> List.List { key : broadKey, value : broadValue })"},{"name":"value","comment":" `Dict` [`MorphValue`](Value-Morph#MorphValue)\n","type":"{ key : Value.Morph.Internal.MorphValue comparableKey, value : Value.Morph.Internal.MorphValue value } -> Value.Morph.Internal.MorphValue (Dict.Dict comparableKey value)"}],"binops":[]},{"name":"Float.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `Float`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#Float)\n\n@docs decimalOrException\n\n","unions":[],"aliases":[],"values":[{"name":"decimalOrException","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a [`Decimal`](Decimal#Decimal) or [`Exception`](Decimal#Exception)\nto a `Float`\n\nKeep in mind that `Decimal -> Float` can be lossy\nsince `Float` is fixed in bit size while [`Decimal`](Decimal#Decimal) is not\n\n[Inverse](Morph#invert) of [`Decimal.Morph.orExceptionFloat`](Decimal-Morph#orExceptionFloat)\n\n","type":"Morph.MorphOrError Basics.Float (Result.Result Decimal.Exception Decimal.Decimal) error_"}],"binops":[]},{"name":"Int.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `Int`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#Int)\n\n@docs integer\n\n","unions":[],"aliases":[],"values":[{"name":"integer","comment":" [`Morph.OneToOne`](Morph#OneToOne) between a [decimal representation](Integer#Integer)\nand an `Int`.\n\nKeep in mind that `Integer -> Int` can overflow\nsince `Int` is fixed in bit size while [`Integer`](Integer#Integer) is not.\n\n[Inverse](Morph#invert) of [`Integer.Morph.int`](Integer-Morph#int)\n\n","type":"Morph.MorphOrError Basics.Int Integer.Integer error_"}],"binops":[]},{"name":"Integer","comment":" Arbitrary-precision whole number. See also [`Integer.Morph`](Integer-Morph)\n\n@docs Integer, Signed\n\n\n## create\n\n@docs fromInt, fromNatural\n\n\n## alter\n\n@docs absolute, negate\n\n\n## transform\n\n@docs toInt\n\nThe type is rarely useful in its current state,\nas the only thing you can do is convert from and to other types.\n\nThis is enough for my use-cases\nbut feel free to PR or open an issue if you'd like to see support\nfor arbitrary-precision arithmetic like addition, multiplication, ...\n\n","unions":[{"name":"Integer","comment":" Arbitrary-precision integer, constructable from bits\n","args":[],"cases":[["N0",[]],["Signed",["Integer.Signed"]]]}],"aliases":[{"name":"Signed","comment":" Arbitrary-precision signed [`Integer`](#Integer), constructable from a [`Sign`](Sign#Sign)\nand [`Natural.AtLeast1` bits](Natural#AtLeast1)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { sign : Sign.Sign, absolute : Natural.AtLeast1 }"}],"values":[{"name":"absolute","comment":" Remove its [`Sign`](Sign#Sign)\n","type":"Integer.Integer -> Natural.Natural"},{"name":"fromInt","comment":" Convert from an `Int`\n","type":"Basics.Int -> Integer.Integer"},{"name":"fromNatural","comment":" Convert from a [`Natural`](Natural#Natural)\n","type":"Natural.Natural -> Integer.Integer"},{"name":"negate","comment":" Flip its [`Sign`](Sign#Sign)\n","type":"Integer.Integer -> Integer.Integer"},{"name":"toInt","comment":" Convert to an `Int`\n\nKeep in mind that this can overflow\nsince `Int` is fixed in bit size while [`Integer`](Integer#Integer) is not.\n\n","type":"Integer.Integer -> Basics.Int"}],"binops":[]},{"name":"Integer.Morph","comment":" [`Morph`](Morph#Morph) for an [arbitrary-sized `Integer`](Integer#Integer)\n\n@docs int, decimal\n@docs value\n\n\n## row\n\n@docs chars, bits\n\n","unions":[],"aliases":[],"values":[{"name":"bits","comment":" [`MorphRow`](Morph#MorphRow) from a given count of [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)s\nin 2's complement,\nand with a given [endianness](https://dark.elm.dmy.fr/packages/elm/bytes/latest/Bytes#Endianness).\n\nFor [`toBroad`](Morph#toBroad): If the number is greater than the capacity possible with the given bit count,\nthe greatest possible value will be returned instead.\n\n","type":"Bytes.Endianness -> N.N (N.In (N.On (N.Add1 minFrom1_)) (N.Up maxX_ N.To (N.Add1 maxFrom1PlusX_))) -> Morph.MorphRow Integer.Integer Bit.Bit"},{"name":"chars","comment":" [`MorphRow`](Morph#MorphRow) from `Char`s.\n\nYou can then of course work with the [`Integer`](Integer#Integer) type directly,\nor convert it to for example an `Int`\n\n    import Morph\n    import List.Morph\n    import Int.Morph\n\n    -- works with natural numbers\n    \"123\"\n        |> Morph.toNarrow\n            (Int.Morph.integer\n                |> Morph.overRow Integer.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok 123\n\n    -- works with negative numbers\n    \"-123\"\n        |> Morph.toNarrow\n            (Int.Morph.integer\n                |> Morph.overRow Integer.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok -123\n\n    -- a decimal number is _not_ an integer\n    \"3.14\"\n        |> Morph.toNarrow\n            (Int.Morph.integer\n                |> Morph.overRow Integer.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n    -- exponential notation, other letters, symbols etc make it fail\n    \"3e10\"\n        |> Morph.toNarrow\n            (Int.Morph.integer\n                |> Morph.overRow Integer.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"Morph.MorphRow Integer.Integer Char.Char"},{"name":"decimal","comment":" [`Morph`](Morph#Morph) from a [`Decimal`](Decimal#Decimal)\nwithout digits after the decimal point.\n\nOther possibilities of handling the fraction after the decimal points are\n\n  - [`Decimal.truncate`](Decimal#truncate)\n  - [`Decimal.floor`](Decimal#floor)\n  - [`Decimal.ceiling`](Decimal#ceiling)\n\n","type":"Morph.Morph Integer.Integer Decimal.Decimal"},{"name":"int","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an `Int`.\n\nKeep in mind that `Integer -> Int` can overflow\nsince `Int` is fixed in bit size while [`Integer`](Integer#Integer) is not.\n\n[Inverse](Morph#invert) of [`Int.Morph.integer`](Int-Morph#integer)\n\n","type":"Morph.MorphOrError Integer.Integer Basics.Int error_"},{"name":"value","comment":" [`MorphValue`](Value-Morph#MorphValue) from an [`Integer`](Integer#Integer)\n","type":"Value.Morph.Internal.MorphValue Integer.Integer"}],"binops":[]},{"name":"Json","comment":" JSON. See also [`Json.Morph`](Json-Morph)\n\n@docs Json, Atom, Composed, Tagged\n\n\n## create\n\n@docs fromValue\n\n\n## transform\n\n@docs toValue\n\n","unions":[{"name":"Atom","comment":" json atom. null/bool/[number](Decimal#Decimal) or string\n","args":[],"cases":[["Null",["()"]],["Bool",["Basics.Bool"]],["Number",["Decimal.Decimal"]],["String",["String.String"]]]},{"name":"Composed","comment":" json structure. record/object/dict or array\n","args":[],"cases":[["Array",["Array.Array Json.Json"]],["Object",["List.List Json.Tagged"]]]}],"aliases":[{"name":"Json","comment":" A valid JSON value. `case`able. Elm doesn't crash on `==`.\nCan't contain any [spooky impure stuff](Json-Morph#JsValueMagic)\n","args":[],"type":"Value.AtomOrComposed Json.Atom Json.Composed"},{"name":"Tagged","comment":" tag-[value](#Json) pair used to represent a field\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { tag : String.String, value : Json.Json }"}],"values":[{"name":"fromValue","comment":" Convert from a [generic representation of an elm value](Value#Value)\n","type":"Value.Value String.String -> Json.Json"},{"name":"toValue","comment":" Convert to a [generic representation of an elm value](Value#Value)\n","type":"Json.Json -> Value.Value String.String"}],"binops":[]},{"name":"Json.Morph","comment":" [Morph](Morph#Morph) [JSON](Json)\n\n@docs compact, value\n@docs string, stringBroadWith\n@docs JsValueMagic, jsValueMagic\n\n","unions":[],"aliases":[{"name":"JsValueMagic","comment":" A value from the javascript side:\nfrom a [`port`](https://guide.elm-lang.org/interop/ports.html),\non `init`,\nfrom [`elm/http`](https://package.elm-lang.org/packages/elm/http/latest), ...\n\nCompiler magic. Not `case`able. Elm crashes on `==`.\nCan include functions, proxies, getters, bigInts, anything\n\nand.. of course this can be abused to break elm's promises 🙈, see for example\n[randomness without `Cmd` ellie](https://ellie-app.com/hpXzJxh4HRda1)\n\n","args":[],"type":"Json.Encode.Value"}],"values":[{"name":"compact","comment":" With compact indexes. Use in combination with [`Value.Morph.eachTag`](Value-Morph#eachTag)\njust before chaining to [`Value.Morph.json`](Value-Morph#json)\n\n  - part tag = [`part` `MorphValue`](Value-Morph#part) index index in the builder\n  - variant tag = [`variant` `MorphValue`](Value-Morph#variant) index in the builder\n  - →\n      - unreadable to humans\n      - only readable by other tools if they know the variant and field order\n      - not easily debuggable\n      - shuffling [`Value.Morph.part`](Value-Morph#part) order → breaking change\n      - renaming [`Value.Morph.part`](Value-Morph#part)s → no change\n\nSee also [`Value.Morph.descriptive`](Value-Morph#descriptive)\n\n","type":"Morph.MorphIndependently (String.String -> Result.Result error_ Value.IndexOrName) (Value.IndexAndName -> String.String)"},{"name":"jsValueMagic","comment":" [Morph](Morph#Morph) to valid [`Json` value](Json#Json) format from [`JsValueMagic`](#JsValueMagic)\n\nAbout json numbers...\n\n  - json numbers don't strictly adhere to a `Float`\n    as defined in the [IEEE 754 standard][ieee]\n    which is hardcoded into almost all CPUs.\n    This standard allows `Infinity` and `NaN` which the [json.org spec][json] does not include.\n  - [`elm/json` silently encodes both as `null`](https://github.com/elm/json/blob/0206c00884af953f2cba8823fee111ee71a0330e/src/Json/Encode.elm#L106).\n    This behavior matches `JSON.stringify` behavior in plain JS\n  - our json representation doesn't have this footgun since it uses [`Decimal`](Decimal#Decimal)\n  - elm `Decoder`s/`Encoder`s can only handle `Float` range which dictates the range we can use for [`Decimal`](Decimal#Decimal)s\n\n[ieee]: https://en.wikipedia.org/wiki/IEEE_754\n[json]: https://www.json.org/\n\n","type":"Morph.Morph Json.Json Json.Morph.JsValueMagic"},{"name":"string","comment":" [Morph](Morph#Morph) from a `String`\n\n[Broadens](Morph#toBroad) to a compact `String`.\nTo adjust format readability → [`stringBroadWith`](#stringBroadWith)\n\n","type":"Morph.Morph Json.Json String.String"},{"name":"stringBroadWith","comment":" [`Json.string`](#string) [Morph](Morph#Morph) with adjustable indentation.\n\nThis is a bit clunky since `stringBroadWith` is using [`Json.Encode.encode`](https://dark.elm.dmy.fr/packages/elm/json/latest/Json-Encode#encode).\nI bet we could make this cleaner with a custom [`MorphRow`](Morph#MorphRow)\nand a nice pretty-printable broad representation like [`the-sett/elm-pretty-printer`](https://github.com/the-sett/elm-pretty-printer/blob/3.0.0/src/Internals.elm#L4).\n\n","type":"{ indentation : Basics.Int } -> Morph.Morph Json.Json String.String"},{"name":"value","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a [generic representation of an elm value](Value#Value)\n\n[Inverse](Morph#invert) of [`Value.Morph.json`](Value-Morph#json)\n\n","type":"Morph.MorphOrError Json.Json (Value.Value String.String) error_"}],"binops":[]},{"name":"List.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `List element`](https://dark.elm.dmy.fr/packages/elm/core/latest/List)\n\n\n## alter\n\n@docs each\n\n\n## sequence\n\n@docs sequenceMap, broadSequenceMap\n\n\n## transform\n\n@docs stack, array, arraySized, string, set, dict\n@docs bytes, value\n\n","unions":[],"aliases":[],"values":[{"name":"array","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an `Array`\n\n    import Array\n    import Morph\n\n    Array.fromList [ 0, 1, 2, 3 ]\n        |> Morph.mapTo List.Morph.array\n    --> [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`Array.Morph.list`](Array-Morph#list)\n\n","type":"Morph.MorphIndependently (Array.Array narrowElement -> Result.Result error_ (List.List narrowElement)) (List.List element -> Array.Array element)"},{"name":"arraySized","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an [`ArraySized`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typesafe-array/latest/)\n\n    import ArraySized\n    import Morph\n\n    ArraySized.l4 0 1 2 3\n        |> Morph.mapTo List.Morph.arraySized\n    --> [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`ArraySized.Morph.list`](ArraySized-Morph#list)\n\n","type":"Morph.MorphIndependently (ArraySized.ArraySized narrowElement narrowRange_ -> Result.Result error_ (List.List narrowElement)) (List.List broadElement -> ArraySized.ArraySized broadElement (N.Min (N.Up0 broadX_)))"},{"name":"broadSequenceMap","comment":" Match broad [`MorphRow`](Morph#MorphRow)s\n(those that can always produce the same broad value)\nbased on given input elements in sequence.\n\nThis can get verbose, so create helpers with it where you see common patterns!\n\n    import Morph exposing (MorphRow)\n    import Char.Morph\n    import List.Morph\n\n    textOnly : String -> MorphRow () Char\n    textOnly stringConstant =\n        List.Morph.broadSequenceMap\n            (Char.Morph.only >> Morph.one)\n            (stringConstant |> String.toList)\n\n    -- Match a specific character, case sensitive\n    \"abc\"\n        |> Morph.toNarrow\n            (textOnly \"abc\" |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok ()\n\n    -- It fails if it's not _exactly_ the same\n    \"abC\"\n        |> Morph.toNarrow\n            (textOnly \"abc\" |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\nNote that `textOnly` is available as `String.Morph.only`.\nOthers aren't, tho, like when matching only a specific\nsequence of [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/)s\n\n","type":"(element -> Morph.MorphRow () broadElement) -> List.List element -> Morph.MorphRow () broadElement"},{"name":"bytes","comment":" [`Morph.OneToOne`](Morph#OneToOne) from [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/)\nto a list of individual bits.\nNow you can [morph them as a row](Morph#MorphRow)!\n","type":"Morph.MorphOrError (Emptiable.Emptiable (Stack.Stacked Bit.Bit) Possibly.Possibly) Bytes.Bytes error_"},{"name":"dict","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `Dict key value` to a `List { key : key, value : value }`.\n\n    import Dict\n    import List.Morph\n    import Morph\n\n    Dict.empty\n        |> Dict.insert 0 'a'\n        |> Dict.insert 1 'b'\n        |> Morph.mapTo List.Morph.dict\n    --> [ { key = 0, value = 'a' }, { key = 1, value = 'b' } ]\n\n[Inverse](Morph#invert) of [`Dict.Morph.list`](Dict-Morph#list)\n\n","type":"Morph.MorphIndependently (Dict.Dict broadKey broadValue -> Result.Result error_ (List.List { key : broadKey, value : broadValue })) (List.List { key : comparableNarrowKey, value : narrowValue } -> Dict.Dict comparableNarrowKey narrowValue)"},{"name":"each","comment":" [`Morph`](Morph#Morph) all elements.\nOn the narrowing side all [narrowed](Morph#toNarrow) values must be `Ok`\nfor it to not result in a [`Morph.Error`](Morph#Error)\n\nIf the element [`Morph`](Morph#Morph) is [`OneToOne`](Morph#OneToOne),\n`each` will always succeed with the type knowing it does\n\n","type":"Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (List.List beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) (List.List narrow)) (List.List beforeToBroad -> List.List broad)"},{"name":"sequenceMap","comment":" From the elements in a given `List`,\ncreate [`MorphRow`](Morph#MorphRow)s\nthat will be run in the same order, one after the other.\n\nSome also call this \"traverse\" (or \"for\" when the arguments are flipped)\n\n    import Morph exposing (MorphRow)\n    import String.Morph\n    import AToZ\n\n    \"helloTHEREcooorwhat\"\n        |> Morph.toNarrow\n            (List.Morph.sequenceMap casedStringOnly [ \"hello\", \"there\", \"coo\", \"or\", \"what\" ]\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok [ AToZ.CaseLower, AToZ.CaseUpper, AToZ.CaseLower, AToZ.CaseLower, AToZ.CaseLower ]\n\n    casedStringOnly : String -> MorphRow AToZ.Case Char\n    casedStringOnly string =\n        Morph.choice\n            (\\lower upper cased ->\n                case cased of\n                    AToZ.CaseLower -> lower ()\n                    AToZ.CaseUpper -> upper ()\n            )\n            |> Morph.rowTry (\\() -> AToZ.CaseLower)\n                (String.Morph.only (string |> String.toLower))\n            |> Morph.rowTry (\\() -> AToZ.CaseUpper)\n                (String.Morph.only (string |> String.toUpper))\n            |> Morph.choiceFinish\n\n**Don't try to be clever with this.**\n\nThe usual [`Morph.narrow`](Morph#narrow)`(\\... -> ...) |>`[`grab`](Morph#grab)-[`match`](Morph#match) chain\nis often more explicit, descriptive and type-safe.\n\nBecause of this, `List.Morph` only exposes `sequenceMap`, not `sequence`,\nmaking misuse a bit more obvious.\n\nIf each element's [`MorphRow`](Morph#MorphRow)\nwill always produce the same broad value like [`String.Morph.only`](String-Morph#only),\nuse [`broadSequenceMap`](#broadSequenceMap)\n\n","type":"(element -> Morph.MorphRow narrow broadElement) -> List.List element -> Morph.MorphRow (List.List narrow) broadElement"},{"name":"set","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `Set`\n\n    import Set\n    import Morph\n\n    Set.fromList [ 0, 1, 2, 3 ]\n        |> Morph.mapTo List.Morph.set\n    --> [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`Set.Morph.list`](Set-Morph#list)\n\n","type":"Morph.MorphIndependently (Set.Set narrowElement -> Result.Result error_ (List.List narrowElement)) (List.List comparableBroadElement -> Set.Set comparableBroadElement)"},{"name":"stack","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a [stack](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack)\n\n    import Stack\n    import Morph\n\n    Stack.topBelow 0 [ 12, 3 ]\n        |> Morph.mapTo List.Morph.stack\n    --> [ 0, 12, 3 ]\n\n[Inverse](Morph#invert) of [`Stack.Morph.list`](Stack-Morph#list)\n\n","type":"Morph.MorphIndependently (Emptiable.Emptiable (Stack.Stacked broadElement) Possibly.Possibly -> Result.Result error_ (List.List broadElement)) (List.List narrowElement -> Emptiable.Emptiable (Stack.Stacked narrowElement) Possibly.Possibly)"},{"name":"string","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `String` to a `List Char`.\n\n[Inverse](Morph#invert) of [`String.Morph.list`](String-Morph#list)\n\n","type":"Morph.MorphOrError (List.List Char.Char) String.String error_"},{"name":"value","comment":" `List` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue element -> Value.Morph.Internal.MorphValue (List.List element)"}],"binops":[]},{"name":"Maybe.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `Maybe content`](https://dark.elm.dmy.fr/packages/elm/core/latest/Maybe#Maybe)\n\n@docs value, toJust, row\n\n","unions":[],"aliases":[],"values":[{"name":"row","comment":" Try to [`Morph`](Morph#Morph) a value and return it as a `Just`.\nIf something fails, go back to where you started and return `Nothing`\n\n> ℹ️ Equivalent regular expression: `?`\n\n    import AToZ\n    import AToZ.Morph\n    import List.Morph\n    import Morph\n\n    -- maybe we get `Just` a letter\n    \"a\"\n        |> Morph.toNarrow\n            (Maybe.Morph.row (AToZ.Morph.lowerChar |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok (Just AToZ.A)\n\n    -- maybe we get `Nothing`\n    \"\"\n        |> Morph.toNarrow\n            (Maybe.Morph.row (AToZ.Morph.char |> Morph.one)\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok Nothing\n\n","type":"Morph.MorphRow contentNarrow broadElement -> Morph.MorphRow (Maybe.Maybe contentNarrow) broadElement"},{"name":"toJust","comment":" `Just content` succeeds with the `content`, `Nothing` fails.\n\n    import Morph\n    import Char.Morph\n\n    Just 'Y'\n        |> Morph.toNarrow\n            (Char.Morph.only 'Y'\n                |> Morph.over Maybe.Morph.toJust\n            )\n    --> Ok ()\n\n","type":"Morph.MorphIndependently (Maybe.Maybe narrowContent -> Result.Result Morph.Error narrowContent) (broadContent -> Maybe.Maybe broadContent)"},{"name":"value","comment":" `Maybe` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue element -> Value.Morph.Internal.MorphValue (Maybe.Maybe element)"}],"binops":[]},{"name":"Morph","comment":" Call it Codec, ParserPrinter, TransformReversible, ...\nWe call it\n\n@docs Morph, OneToOne, MorphOrError, MorphIndependently\n\n\n# create\n\n@docs oneToOne, broad, toggle, keep, oneToOneOn\n@docs only, custom\n\nNote that there are no \"validate\" or \"filter\" primitives\nto encourage narrowing down the type when limiting values:\n[\"Parse, don't validate\"](https://elm-radio.com/episode/parse-dont-validate/).\nThat's a core idea in elm. You'll find lots of legendary resources on this topic.\n\nNarrowing gives you\n\n  - a better error description out of the box\n  - a more descriptive and correct type\n  - building invalid values becomes impossible\n\n```\nprintable : Morph LocalSymbolPrintable Char (Morph.Error Char)\nprintable =\n    Morph.choice\n        (\\exclamationMark numberSign dollarSign percentSign ampersand asterisk lowLine hyphenMinus backSlash printable ->\n            case printable of\n                ExclamationMark ->\n                    exclamationMark ()\n\n                NumberSign ->\n                    numberSign ()\n\n                DollarSign ->\n                    dollarSign ()\n\n                PercentSign ->\n                    percentSign ()\n\n                Ampersand ->\n                    ampersand ()\n\n                Asterisk ->\n                    asterisk ()\n\n                LowLine ->\n                    lowLine ()\n\n                HyphenMinus ->\n                    hyphenMinus ()\n        )\n        |> Morph.try (\\() -> ExclamationMark) (Char.Morph.only '!')\n        |> Morph.try (\\() -> NumberSign) (Char.Morph.only '#')\n        |> Morph.try (\\() -> DollarSign) (Char.Morph.only '$')\n        |> Morph.try (\\() -> PercentSign) (Char.Morph.only '%')\n        |> Morph.try (\\() -> Ampersand) (Char.Morph.only '&')\n        |> Morph.try (\\() -> Asterisk) (Char.Morph.only '*')\n        |> Morph.try (\\() -> LowLine) (Char.Morph.only '_')\n        |> Morph.try (\\() -> HyphenMinus) (Char.Morph.only '-')\n        |> Morph.choiceFinish\n```\n\n@docs recursive\n\n\n# convert using a morph\n\n@docs toBroad, toNarrow, mapTo\n\n\n# row\n\n@docs MorphRow, MorphRowIndependently, rowFinish\n\n\n## create row\n\n@docs end, one, narrow, grab, match\n\n\n# alter\n\n@docs named\n@docs invert\n@docs deadEndMap\n@docs deadEndNever, errorMap\n\n\n# error\n\n@docs Error, ErrorWithDeadEnd, PartsError, SequenceError, SequencePlace, ChainError, ChainPlace, UntilError, CountAndExactlyElementSequenceError\n\n\n# describe\n\n@docs description\n@docs Description, ChainDescription, SequenceDescription, UntilDescription\n\n\n# error and description visualization\n\n@docs descriptionToTree, DescriptionKind\n@docs descriptionAndErrorToTree, DescriptionOrErrorKind\n\nYou'll usually want to present this tree as an expandable view.\nIn [examples](https://github.com/lue-bird/elm-morph/tree/master/example), we have a minimal custom implementation of that.\n\nI'm sure you'd want to present it differently in your app (css support, better accessibility, more consistent style, more features etc.).\nSince a tree-view isn't the focus of this package, no half-hearted component like that is exposed.\nFrankly I also can't recommend any existing package for this either; existing solutions to me seemed lacking.\n\nMaybe you've found or built some nice tree-view? Please share it :)\n\n@docs treeToLines\n\n\n# chain\n\n@docs over, overRow\n\nIf you're missing something more \"I need a length andThen I can construct this many elements\"-like,\ntry [`ArraySized.Morph.exactlyWith`](ArraySized-Morph#exactlyWith).\n\n\n# [`Morph`](Morph#Morph) by part\n\n@docs PartsMorphEmptiable\n@docs parts, part, partsFinish\n\n\n# choice [`Morph`](Morph#Morph)\n\n[`Morph`](#Morph) a union `type`\n\n\n## [`Morph`](Morph#Morph) by variant\n\n@docs VariantsMorphEmptiable, variants, variant, variantsFinish\n@docs choice\n@docs ChoiceMorphEmptiable, try, choiceFinish\n\n\n## dynamic list of possibilities\n\n@docs tryTopToBottom\n\n\n# choice [`MorphRow`](#MorphRow)\n\n@docs ChoiceMorphRowEmptiable, rowTry\n\n\n# sequence\n\n  - optional → [`Maybe.Morph.row`](Maybe-Morph#row)\n  - [`atLeast`](ArraySized-Morph#atLeast)\n  - [`exactly`](ArraySized-Morph#exactly)\n  - between → [`ArraySized.Morph.in_`](ArraySized-Morph#exactly)\n\n@docs whilePossible\n@docs untilNext, broadEnd, untilLast\n@docs whilePossibleFold, untilNextFold, untilLastFold\n\nSince there is nothing opaque in the Morph type,\nyou can experiment with new primitives etc. without needing to fork `elm-morph`.\n\nI'd love to hear about your findings!\n\n\n# limits of `Morph`\n\n\n## A Morph can only fail one way\n\nBut what if some parts of the broad format are actually more narrow?\n\n\n### solution: require the narrow structure to have equally narrow parts\n\nExample: Your narrow elm value has a `Float` but the broad JSON's number can't have Nan or infinity.\n\nWhat `MorphValue` has settled on is the following:\n\nJSON uses the [`Decimal`](Decimal#Decimal) type which doesn't have exception states.\n\nNow the user has a choice:\n\n  - use [`Decimal`](Decimal#Decimal) instead of `Float` in your code, too, if you don't expect exceptions\n\n  - explicitly encode the exception as well\n\n        Float.Morph.decimalOrException\n            |> Morph.over Decimal.Morph.orExceptionValue\n\nThis is pretty idealistic but if you can do something like this, give it a shot.\n\n\n### solution: 2 separate morphs\n\nExample: translating one programming language to another,\nwhere both can represent stuff the other can't.\nThis can fail in both directions.\n\nI haven't done something like that but both directions to a subset combine well\n\n    LanguageABSubset.a : Morph LanguageABSubset LanguageA\n    -- LanguageABSubset -> LanguageA will always work\n\n    -- and\n\n    LanguageABSubset.b : Morph LanguageABSubset LanguageB\n    -- LanguageABSubset -> LanguageB will always work\n\n    -- combine\n\n    --: LanguageA -> Result Morph.Error LanguageB\n    Morph.toNarrow LanguageABSubset.a >> Result.map (Morph.toBroad LanguageABSubset.b)\n\n    --: LanguageB -> Result Morph.Error LanguageA\n    Morph.toNarrow LanguageABSubset.b >> Result.map (Morph.toBroad LanguageABSubset.a)\n\n\n### Why do most primitives here not allow custom error types?\n\nThey [could](#MorphOrError) but what is the problem you are trying to solve?\n\nErrors with more narrow structural information are mostly useful for recovery based on what went wrong.\n\nIn that case you probably want\n\n    Morph.OneToOne (Result YourRecoverable YourNarrow) YourBroad\n\nSo always having an extra type variable just adds complexity to the types.\n\n\n## A Morph is not a multi-tool\n\nEach `Morph` has one use-case in mind.\nThere is no way to use one Morph\nto build a `Form`, a `Random.Generator`, a `Fuzzer`, a `Decoder`, ...\n\nOne attempt at something like that is [`edkelly303/elm-multitool`](https://dark.elm.dmy.fr/packages/edkelly303/elm-multitool/latest/).\n\n\n# oh look! other projects do similar things\n\n  - haskell: [`invertible-syntax`](https://hackage.haskell.org/package/invertible-syntax),\n    [`partial-isomorphisms`](https://hackage.haskell.org/package/partial-isomorphisms)\n  - python: [`construct`](https://construct.readthedocs.io/en/latest/intro.html) from and to broad bits\n  - rust: [`parse_display`](https://docs.rs/parse-display/latest/parse_display/) for text, less safe and more restrictive\n  - kotlin: [`searles/parsing`](https://github.com/searles/parsing)\n  - js: [`nearley.js`](https://nearley.js.org/)\n  - prolog: [`phrase/2`](https://www.swi-prolog.org/pldoc/doc_for?object=phrase/2) is somewhat similar for text\n  - custom: [FliPpr](https://link.springer.com/article/10.1007/s00354-018-0033-7)\n  - parse-build an enum over a String: [`jmpavlick/bimap`](https://dark.elm.dmy.fr/packages/jmpavlick/bimap/latest/), [`toastal/select-prism`](https://package.elm-lang.org/packages/toastal/select-prism/latest/), [`Herteby/enum`](https://package.elm-lang.org/packages/Herteby/enum/latest), [`genthaler/elm-enum`](https://package.elm-lang.org/packages/genthaler/elm-enum/latest/), [`the-sett/elm-refine` `Enum`](https://package.elm-lang.org/packages/the-sett/elm-refine/latest/Enum)\n  - equivalent to [`Morph.OneToOne`](#OneToOne): [`arturopala/elm-monocle` `Monocle.Iso`](https://package.elm-lang.org/packages/arturopala/elm-monocle/latest/Monocle-Iso), [`Heimdell/elm-optics` `Optics.Core.Iso`](https://package.elm-lang.org/packages/Heimdell/elm-optics/latest/Optics-Core#Iso), [`erlandsona/elm-accessors` `Accessors.Iso`](https://dark.elm.dmy.fr/packages/erlandsona/elm-accessors/latest/Accessors#Iso), [`fujiy/elm-json-convert` `Json.Convert.Iso`](https://package.elm-lang.org/packages/fujiy/elm-json-convert/latest/Json-Convert#Iso)\n  - I expect there to be lots more out there, please send some (PR, issue etc)!\n\n---\n\nUp for a challenge? implement & PR\n\n  - `date`, `time`, `datetime`\n  - `pathUnix`, `pathWindows`\n  - `uri`\n  - `ipV4`, `ipV6`\n\n","unions":[{"name":"ChainPlace","comment":" The more narrow or broad morph in an `narrow |> Morph.over... broad` chain?\n","args":[],"cases":[["ChainPlaceBroad",[]],["ChainPlaceNarrow",[]]]},{"name":"CountAndExactlyElementSequenceError","comment":" An error when using [`ArraySized.Morph.exactlyWith`](ArraySized-Morph#exactlyWith)\n","args":["error"],"cases":[["CountError",["error"]],["ExactlyCountElementSequenceError",["{ error : error, startsDownInBroadList : Emptiable.Emptiable (Stack.Stacked Basics.Int) Basics.Never }"]]]},{"name":"Description","comment":" Describing what the Morph [narrows to](#toNarrow) and [broadens from](#toBroad)\nin a neatly structured way.\n\nWhy do some variants have type aliases? → To concisely annotate them\nin the implementation of for example [`descriptionAndErrorToTree`](#descriptionAndErrorToTree).\n\n","args":[],"cases":[["InverseDescription",["Morph.Description"]],["CustomDescription",[]],["SucceedDescription",[]],["EndDescription",[]],["WhilePossibleDescription",["Morph.Description"]],["UntilNextDescription",["Morph.UntilDescription"]],["UntilLastDescription",["Morph.UntilDescription"]],["SequenceDescription",["Morph.SequenceDescription"]],["NamedDescription",["{ name : String.String, description : Morph.Description }"]],["OnlyDescription",["String.String"]],["RecursiveDescription",["{ name : String.String, description : () -> Morph.Description }"]],["ChainDescription",["Morph.ChainDescription"]],["ElementsDescription",["Morph.Description"]],["PartsDescription",["Emptiable.Emptiable (Stack.Stacked { tag : String.String, value : Morph.Description }) Basics.Never"]],["ChoiceDescription",["Emptiable.Emptiable (Stack.Stacked Morph.Description) Basics.Never"]],["VariantsDescription",["Emptiable.Emptiable (Stack.Stacked { tag : String.String, value : Morph.Description }) Basics.Never"]]]},{"name":"DescriptionKind","comment":" What does the label in a [description tree](#descriptionToTree) describe?\nIs it a description from some internal control structure\nor a custom description from [`Morph.named`](#named)?\n","args":[],"cases":[["DescriptionNameKind",[]],["DescriptionStructureKind",[]]]},{"name":"DescriptionOrErrorKind","comment":" What does the label in an [error and description tree](#descriptionAndErrorToTree) describe?\nIs it from an error, a [structure description or custom description](#DescriptionKind)?\n","args":[],"cases":[["DescriptionKind",["Morph.DescriptionKind"]],["ErrorKind",[]]]},{"name":"ErrorWithDeadEnd","comment":" [`Error`](#Error) with a custom value on `DeadEnd`\n\n    type alias OneToOne mapped unmapped =\n        MorphOrError mapped unmapped (ErrorWithDeadEnd Never)\n\n`deadEnd` could also be formatted text for display.\nFor that, use [`MorphOrError`](#MorphOrError) [`ErrorWithDeadEnd`](#ErrorWithDeadEnd) doing [`deadEndMap`](#deadEndMap)\non [`Morph`](#Morph) that are returned.\n\nHave trouble doing so because some API is too strict on errors? → issue\n\nWhy do some variants have type aliases? → To concisely annotate them\nin the implementation of for example [`descriptionAndErrorToTree`](#descriptionAndErrorToTree).\n\n","args":["deadEnd"],"cases":[["DeadEnd",["deadEnd"]],["UntilError",["Morph.UntilError (Morph.ErrorWithDeadEnd deadEnd)"]],["SequenceError",["Morph.SequenceError (Morph.ErrorWithDeadEnd deadEnd)"]],["ChainError",["Morph.ChainError (Morph.ErrorWithDeadEnd deadEnd)"]],["ElementsError",["Emptiable.Emptiable (Stack.Stacked { location : String.String, error : Morph.ErrorWithDeadEnd deadEnd }) Basics.Never"]],["CountAndExactlyElementSequenceError",["Morph.CountAndExactlyElementSequenceError (Morph.ErrorWithDeadEnd deadEnd)"]],["PartsError",["Morph.PartsError (Morph.ErrorWithDeadEnd deadEnd)"]],["VariantError",["{ index : Basics.Int, error : Morph.ErrorWithDeadEnd deadEnd }"]],["ChoiceError",["Emptiable.Emptiable (Stack.Stacked (Morph.ErrorWithDeadEnd deadEnd)) Basics.Never"]]]},{"name":"SequencePlace","comment":" At the first section (early) or after that (late) in the sequence?\n","args":[],"cases":[["SequencePlaceEarly",[]],["SequencePlaceLate",[]]]}],"aliases":[{"name":"ChainDescription","comment":" [Description](#Description) specific to\n[`narrow |> Morph.overRow broad`](#overRow) and [`narrow |> Morph.over broad`](#over)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { broad : Morph.Description, narrow : Morph.Description }"},{"name":"ChainError","comment":" [Error](#Error) specific to\n[`narrow |> Morph.overRow broad`](#overRow) and [`narrow |> Morph.over broad`](#over)\n\nSince this is a sequence, failure can happen [at the broader transformation or the narrower transformation](#ChainPlace)\n\n","args":["error"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { place : Morph.ChainPlace, error : error }"},{"name":"ChoiceMorphEmptiable","comment":" Possibly incomplete [`Morph`](Morph#Morph) for a choice type.\nSee [`Morph.choice`](Morph#choice), [`try`](#try), [`choiceFinish`](#choiceFinish)\n","args":["noTryPossiblyOrNever","choiceNarrow","choiceBeforeNarrow","choiceToBroad","error"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { description : Emptiable.Emptiable (Stack.Stacked Morph.Description) noTryPossiblyOrNever, toNarrow : choiceBeforeNarrow -> Result.Result (Emptiable.Emptiable (Stack.Stacked error) noTryPossiblyOrNever) choiceNarrow, toBroad : choiceToBroad }"},{"name":"ChoiceMorphRowEmptiable","comment":" Possibly incomplete [`MorphRow`](#MorphRow) for a choice/variant type/custom type.\nSee [`Morph.choice`](Morph#choice), [`Morph.rowTry`](#rowTry), [`Morph.choiceFinish`](#choiceFinish)\n","args":["noTryPossiblyOrNever","choiceNarrow","choiceToBroad","broadElement"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { description : Emptiable.Emptiable (Stack.Stacked Morph.Description) noTryPossiblyOrNever, toNarrow : List.List broadElement -> Result.Result (Emptiable.Emptiable (Stack.Stacked Morph.Error) noTryPossiblyOrNever) { narrow : choiceNarrow, broad : List.List broadElement }, toBroad : choiceToBroad }"},{"name":"Error","comment":" Where and why [narrowing](#toNarrow) has failed.\n\nEach dead is a `String`.\n\nOpen an issue if a String is not enough for the kinds of errors you want to display.\n\nIn theory one can use [`MorphOrError`](#MorphOrError) [`ErrorWithDeadEnd`](#ErrorWithDeadEnd)\ndoing [`deadEndMap`](#deadEndMap) on [`Morph`](#Morph)s like `only`\nbut the current API is quite restrictive on errors to avoid complexity in Morph types.\n\n","args":[],"type":"Morph.ErrorWithDeadEnd String.String"},{"name":"Morph","comment":" Conversion functions from a more general (we say broad) to\na more specific (we say narrow) format and back.\n\nEach type `Morph narrow broad`,\nsay for example `Morph Email String`, can convert\n\n\n### `toBroad : narrow -> broad`\n\n  - example: `Email -> String`\n  - going from a specific type to a general one\n  - always successful\n\n\n### `toNarrow : broad -> Result error narrow`\n\n  - example: `String -> Result Morph.Error Email`\n  - going from a general type to a specific one\n  - the result can always be turned back successfully\n  - 📰 [blog post \"A Broader Take on Parsing\" by Joël Quenneville](https://thoughtbot.com/blog/a-broader-take-on-parsing?utm_campaign=Elm%20Weekly&utm_medium=email&utm_source=Revue%20newsletter)\n    captures the essence of narrowing and gives more examples\n  - 📰 [blog post \"Shaping Values with Types\" by Josh Clayton](https://thoughtbot.com/blog/shaping-values-with-types?utm_campaign=Elm%20Weekly&utm_medium=email&utm_source=Revue%20newsletter)\n    following the example of an employee id,\n    shows how simply wrapping broad data into an opaque type\n      - doesn't bring safety and peace of mind\n          - for example,\n            you won't have to fix a bug from months ago\n            that interrupts the work when you're swamped with today\n      - opaque types don't save complexity in validation, tests, documentation anyway\n          - doesn't communicate business rules (requirements, ...)\n            including for other developers,\n            \"allowing for improved reasoning across the codebase\"\n  - 🎙️ [podcast \"Parse, don't validate\"](https://elm-radio.com/episode/parse-dont-validate/)\n\n","args":["narrow","broad"],"type":"Morph.MorphOrError narrow broad Morph.Error"},{"name":"MorphIndependently","comment":" Sometimes, you'll see the most general version of [`Morph`](#Morph):\n\n    : MorphIndependently toNarrow toBroad\n    -- or\n    : MorphIndependently\n        (beforeToNarrow -> Result error narrow)\n        (beforeToBroad -> broad)\n\nwhere\n\n  - a `narrow` result can't necessarily be used as input for [`toBroad`](#toBroad)\n  - a `broad` result can't necessarily be used as input for [`toNarrow`](#toNarrow)\n\nFor example:\n\n  - [`MorphValue`](Value-Morph#MorphValue): [`toBroad`](#toBroad) returns a value where we know\n    **both index and name** for each field/variant,\n    whereas [`toNarrow`](#toNarrow) allows **either index or name** for each field/variant.\n    This allows us to choose whether we want a [`descriptive`](Value-Morph#descriptive) or [`compact`](Value-Morph#compact)\n    view at the end, being able to switch anytime or use both for different situations.\n  - [`MorphRow`](#MorphRow): [`toNarrow`](#toNarrow) accepts a row of elements\n    but [`toBroad`](#toBroad) results in a [`Rope`](https://dark.elm.dmy.fr/packages/miniBill/elm-rope/latest/) for better performance\n  - [`Stack.Morph.list`](Stack-Morph#list) etc allow different element types for both directions.\n    This is not necessary at all but allows it to be used more generally.\n\n","args":["toNarrow","toBroad"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { description : Morph.Description, toNarrow : toNarrow, toBroad : toBroad }"},{"name":"MorphOrError","comment":" [`Morph`](#Morph) that can [narrow](#toNarrow)\nto an error that can be different from the default [`Error`](#Error).\n\n    type alias OneToOne mapped unmapped =\n        MorphOrError mapped unmapped (ErrorWithDeadEnd Never)\n\n    type alias Morph narrow broad =\n        MorphOrError narrow broad (ErrorWithDeadEnd String)\n\nThis type is used to annotate [`Morph.OneToOne`](#OneToOne) results,\nso instead of\n\n    String.Morph.list : Morph.OneToOne String (List Char)\n    String.Morph.list =\n        Morph.oneToOne String.fromList String.toList\n\nit's annotated\n\n    String.Morph.list : MorphOrError String (List Char) error_\n    String.Morph.list =\n        Morph.oneToOne String.fromList String.toList\n\nto allow mixing `String.Morph.list` with fallible morphs.\n\n","args":["narrow","broad","error"],"type":"Morph.MorphIndependently (broad -> Result.Result error narrow) (narrow -> broad)"},{"name":"MorphRow","comment":" Parser-printer:\n\n  - The parser part: Consume some broad elements\n    and return either a narrow value or an [`Error`](#Error)\n\n  - The printer part: Turn a narrow value back into broad elements\n\nSo to morph broad characters,\n\n    type alias MorphString narrow =\n        MorphRow narrow Char\n\n\n### example: 2D point\n\n    import Morph exposing (MorphRow, match, grab, broad)\n    import Integer.Morph\n    import Int.Morph\n    import String.Morph\n    import List.Morph\n    -- from lue-bird/elm-no-record-type-alias-constructor-function\n    import RecordWithoutConstructorFunction exposing (RecordWithoutConstructorFunction)\n\n    type alias Point =\n        -- makes `Point` constructor function unavailable\n        RecordWithoutConstructorFunction\n            { x : Int\n            , y : Int\n            }\n\n    -- successful parsing looks like\n    \"(271, 314)\"\n        |> Morph.toNarrow\n            (point\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok { x = 271, y = 314 }\n\n    -- building always works\n    { x = 271, y = 314 }\n        |> Morph.toBroad\n            (point\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> \"( 271, 314 )\"\n\n    point : MorphRow Point Char\n    point =\n        Morph.narrow (\\x y -> { x = x, y = y })\n            |> match (String.Morph.only \"(\")\n            |> match (broad [ () ] |> Morph.overRow spaces)\n            |> grab .x (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n            |> match (broad [] |> Morph.overRow spaces)\n            |> match (String.Morph.only \",\")\n            |> match (broad [ () ] |> Morph.overRow spaces)\n            |> grab .y (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n            |> match (broad [ () ] |> Morph.overRow spaces)\n            |> match (String.Morph.only \")\")\n\n    spaces : MorphRow (List ()) Char\n    spaces =\n        Morph.named \"spaces\"\n            (Morph.whilePossible (String.Morph.only \" \"))\n\n    \"(271, x)\"\n        |> Morph.toNarrow\n            (point\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n        |> Result.toMaybe\n    --> Nothing\n\nNote before we start:\n`MorphRow` _always backtracks_ and never commits to a specific path!\n\n  - 👍 improves readability\n\n    crucial so we don't experience reports like\n\n    > \"If it compiles it runs\"\n    >\n    > Unless you are writing a parser.\n    >\n    > The parser doesn't care.\n    >\n    > The parser will compile and then murder you for breakfast.\n\n    – xarvh (Francesco Orsenigo) on slack\n\n  - 👍 errors will always show all options and why they failed\n\n  - 👎 performs worse as there are more [possibilities](Morph#rowTry) to parse to know it failed\n\n","args":["narrow","broadElement"],"type":"Morph.MorphIndependently (List.List broadElement -> Result.Result Morph.Error { narrow : narrow, broad : List.List broadElement }) (narrow -> Rope.Rope broadElement)"},{"name":"MorphRowIndependently","comment":" Incomplete [`MorphRow`](#MorphRow) for a thing composed of multiple parts = group.\nIt's what you supply during a [`Morph.narrow`](Morph#narrow)`|>`[`grab`](#grab)/[`match`](#match) build\n","args":["narrow","beforeToBroad","broadElement"],"type":"Morph.MorphIndependently (List.List broadElement -> Result.Result Morph.Error { narrow : narrow, broad : List.List broadElement }) (beforeToBroad -> Rope.Rope broadElement)"},{"name":"OneToOne","comment":" [`Morph`](#Morph) between representations\nthat have the same structural information\nand can be mapped 1:1 into each other.\n[narrowing](#mapTo) can `Never` fail.\n\nExamples:\n\n  - you need a different narrow type\n\n        Morph.oneToOne Set.toList Set.fromList\n            |> Morph.over (Value.list elementMorph)\n\n    Btw that `oneToOne` is available as [`Set.Morph.list`](Set-Morph#list). Other examples\n\n      - [`List.Morph.array`](List-Morph#array), [`Array.Morph.list`](Array-Morph#list)\n      - [`String.Morph.stack`](String-Morph#stack), [`Stack.Morph.string`](Stack-Morph#string)\n      - ...\n\n  - strip unnecessary information\n    `{ end : (), before : List element } -> List element`\n\n        Morph.oneToOne .before\n            (\\before_ -> { before = before_, end = () })\n\n    Btw that `oneToOne` is available as [`broadEnd`](#broadEnd)\n\nOnly use [`Morph.OneToOne`](#OneToOne) to annotate _arguments_.\nFor results, leave the error variable.\n\n    MorphOrError (List Char) String error_\n\nallows it to be mixed with other [`Morph`](#Morph)s that can actually fail.\n\nSince both type arguments of `OneToOne` are equally narrow/broad,\nchoosing one as the `mapped` and one as the `unmapped` is rather arbitrary.\n\nThat's the reason we usually expose 2 versions: `A.Morph.b` & `B.Morph.a`.\n\nNote that `OneToOne` doesn't mean that information can't get lost on the way:\n\n    dictFromListMorph =\n        Morph.oneToOne Dict.fromList Dict.toList\n\n`OneToOne` just means that there's no narrowing necessary to translate one state to the other\n\n","args":["mapped","unmapped"],"type":"Morph.MorphOrError mapped unmapped (Morph.ErrorWithDeadEnd Basics.Never)"},{"name":"PartsError","comment":" A group's part [`Error`](#Error)s, each with their part index\n","args":["partError"],"type":"Emptiable.Emptiable (Stack.Stacked { index : Basics.Int, error : partError }) Basics.Never"},{"name":"PartsMorphEmptiable","comment":" [`Morph`](#Morph) on groups in progress.\nStart with [`parts`](#parts), assemble with [`|> part`](#part), finally [`partsFinish`](#partsFinish)\n","args":["noPartPossiblyOrNever","narrow","broaden"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { description : Emptiable.Emptiable (Stack.Stacked { tag : String.String, value : Morph.Description }) noPartPossiblyOrNever, toNarrow : narrow, toBroad : broaden }"},{"name":"SequenceDescription","comment":" [Description](#Description) specific to\n[`MorphRow`](#MorphRow)s following one after the other\nlike with [`|> grab`](#grab), [`|> match`](#match) etc.\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { early : Morph.Description, late : Morph.Description }"},{"name":"SequenceError","comment":" [Error](#Error) specific to\n[`MorphRow`](#MorphRow)s following one after the other\nlike with [`|> grab`](#grab), [`|> match`](#match) etc.\n\nSince this is a sequence, failure can happen [at the first section or after that](#SequencePlace)\n\n","args":["error"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { place : Morph.SequencePlace, error : error, startDownInBroadList : Basics.Int }"},{"name":"UntilDescription","comment":" [`untilNext`](#untilNext) and [`untilNextFold`](#untilNextFold)-specific [`Description`](#Description)\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { end : Morph.Description, element : Morph.Description }"},{"name":"UntilError","comment":" [`Error`](#Error) specific to\n[`untilNext`](#untilNext), [`untilLast`](#untilLast), [`untilNextFold`](#untilNextFold), [`untilLastFold`](#untilLastFold)\n","args":["partError"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { endError : partError, elementError : partError, startsDownInBroadList : Emptiable.Emptiable (Stack.Stacked Basics.Int) Basics.Never }"},{"name":"VariantsMorphEmptiable","comment":" Builder for a [`Morph`](#Morph) to a choice. Possibly incomplete\n\nInitialize with [`Morph.variants`](#variants)\n\n","args":["noTryPossiblyOrNever","narrow","broaden"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { description : Emptiable.Emptiable (Stack.Stacked { tag : String.String, value : Morph.Description }) noTryPossiblyOrNever, toNarrow : narrow, toBroad : broaden }"}],"values":[{"name":"broad","comment":" [`Morph`](#Morph) that when calling [`toBroad`](Morph#toBroad) always returns a given constant.\n\nFor any more complex [`toBroad`](#toBroad) process, use [`oneToOne`](#oneToOne)\n\n","type":"broadConstant -> Morph.MorphIndependently (beforeNarrow_ -> Result.Result error_ ()) (() -> broadConstant)"},{"name":"broadEnd","comment":" [Morph](#MorphRow) multiple elements from now to when `end` matches.\n\n    decoderNameSubject : MorphRow String Char\n    decoderNameSubject =\n        String.Morph.list\n            |> Morph.over Morph.broadEnd\n            |> Morph.overRow\n                (Morph.until\n                    { end = String.Morph.only \"Decoder\"\n                    , element = Morph.keep |> Morph.one\n                    }\n                )\n\nYou might think: Why not use\n\n    decoderNameSubject : MorphRow (List Char) Char\n    decoderNameSubject =\n        Morph.whilePossible (Morph.keep |> Morph.one)\n            |> Morph.match (String.Morph.only \"Decoder\")\n\nProblem is: This will never succeed.\n`whilePossible (Morph.keep |> Morph.one)` always goes on.\nWe never reach the necessary [`match`](#match).\n\n","type":"Morph.Morph (List.List beforeEndElement) { end : (), beforeEnd : List.List beforeEndElement }"},{"name":"choice","comment":" Discriminate into possibilities\n\n    {-| Invisible spacing character\n    -}\n    type Blank\n        = Space\n        | Tab\n        | Return Return\n        | FormFeed\n\n    blankChar : Morph Blank Char (Morph.Error Char)\n    blankChar =\n        Morph.named \"blank\"\n            (Morph.choice\n                (\\spaceVariant tabVariant returnVariant formFeedVariant blankNarrow ->\n                    case blankNarrow of\n                        Space ->\n                            spaceVariant ()\n\n                        Tab ->\n                            tabVariant ()\n\n                        Return return_ ->\n                            returnVariant return_\n\n                        FormFeed ->\n                            formFeedVariant ()\n                )\n                |> Morph.try (\\() -> Space) (Char.Morph.only ' ')\n                |> Morph.try (\\() -> Tab) (Char.Morph.only '\\t')\n                |> Morph.try Return returnChar\n                |> Morph.try (\\() -> FormFeed)\n                    -- \\f\n                    (Char.Morph.only '\\u{000C}')\n                |> Morph.choiceFinish\n            )\n\n    {-| Line break character\n    -}\n    type Return\n        = NewLine\n        | CarriageReturn\n\n    {-| Match a line break character: Either\n\n      - new line `'\\n'`\n      - carriage return `'\\r'`\n\n    > ℹ️ Equivalent regular expression: `[\\n\\r]`\n\n    -}\n    returnChar : Morph Return Char (Morph.Error Char)\n    returnChar =\n        Morph.choice\n            (\\newLineVariant carriageReturnVariant returnNarrow ->\n                case returnNarrow of\n                    NewLine ->\n                        newLineVariant ()\n\n                    CarriageReturn ->\n                        carriageReturnVariant ()\n            )\n            |> Morph.try (\\() -> NewLine)\n                (Char.Morph.only '\\n')\n            |> Morph.try (\\() -> CarriageReturn)\n                -- \\r\n                (Char.Morph.only '\\u{000D}')\n            |> Morph.choiceFinish\n\n    {-| The end of a text line:\n    either a return character or the end of the whole text.\n    -}\n    type LineEnd\n        = InputEnd\n        | Return Return\n\n    {-| Consume the end of the current line or Morph.narrow if there are\n    no more remaining characters in the input text.\n\n    > ℹ️ Equivalent regular expression: `$`\n\n    -}\n    endText : MorphRow Char LineEnd\n    endText =\n        Morph.choice\n            (\\returnVariant inputEndVariant maybeChoice ->\n                case maybeChoice of\n                    Return returnValue ->\n                        returnVariant returnValue\n\n                    InputEnd ->\n                        inputEndVariant ()\n            )\n            |> Morph.rowTry Return\n                (returnChar |> Morph.one)\n            |> Morph.rowTry (\\() -> InputEnd)\n                Morph.end\n            |> Morph.choiceFinish\n\n    -- match a blank\n    \"\\n\\t \"\n        |> Morph.toNarrow\n            (Morph.whilePossible blank\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok [ Return NewLine, Tab, Space ]\n\n    -- anything else makes it fail\n    'a' |> Morph.toNarrow blank |> Result.toMaybe\n    --> Nothing\n\n","type":"broadenByPossibility -> Morph.ChoiceMorphEmptiable Possibly.Possibly choiceNarrow_ choiceBroad_ broadenByPossibility error_"},{"name":"choiceFinish","comment":" Always the last step of a [`Morph.choice`](Morph#choice) [`|> Morph.try`](Morph#try) or [`|> Morph.rowTry`](#rowTry) builder\n","type":"Morph.ChoiceMorphEmptiable Basics.Never choiceNarrow choiceBeforeNarrow (choiceBeforeToBroad -> choiceBroad) (Morph.ErrorWithDeadEnd deadEnd) -> Morph.MorphIndependently (choiceBeforeNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) choiceNarrow) (choiceBeforeToBroad -> choiceBroad)"},{"name":"custom","comment":" Create a custom morph for a value by explicitly specifying\n\n  - a `String` description\n  - `toNarrow`: a transformation that can fail with any error consistent with your other errors (so most likely a string)\n  - `toBroad`: a transformation that can build the parsed value back to what a value that can be parsed\n\nA common use-case is narrowing to one of multiple variants.\nExample: only succeed with an int-like expression:\n\n    intLike : Morph Int Number\n    intLike =\n        Morph.custom \"int-like\"\n            { toBroad = IntValue\n            , toNarrow =\n                \\value ->\n                    case value of\n                        IntValue intValue ->\n                            intValue |> Ok\n\n                        HexValue hexIntValue ->\n                            hexIntValue |> Ok\n\n                        FloatValue _ ->\n                            \"float\" |> Err\n            }\n\n","type":"String.String -> { toNarrow : beforeToNarrow -> Result.Result deadEnd narrow, toBroad : beforeToBroad -> broad } -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad)"},{"name":"deadEndMap","comment":" Change all [`DeadEnd`](#ErrorWithDeadEnd)s based on their current values.\n\n`deadEnd` can for example be changed to formatted text for display.\nFor that, use [`MorphOrError`](#MorphOrError) [`ErrorWithDeadEnd`](#ErrorWithDeadEnd) doing [`deadEndMap`](#deadEndMap)\non [`Morph`](#Morph) that are returned.\n\nHave trouble doing so because some API is too strict on errors? → issue\n\nSee also: [`deadEndNever`](#deadEndNever)\n\n","type":"(deadEnd -> deadEndChanged) -> Morph.ErrorWithDeadEnd deadEnd -> Morph.ErrorWithDeadEnd deadEndChanged"},{"name":"deadEndNever","comment":" An [`Error`](#ErrorWithDeadEnd) where running into a dead end is impossible.\n\nBecause each kind of error needs at least one dead end, no such error can be created.\nTherefore, you can treat it as _any_ value.\n\nUnder the hood, only [`Basics.never`](https://dark.elm.dmy.fr/packages/elm/core/latest/Basics#never)\nit's as safe as any other elm code.\n\n[`deadEndNever`](#deadEndNever) can be useful with [`errorMap`](#errorMap)\nto convert a `MorphOrError ... (ErrorWithDeadEnd Never)` to `MorphOrError ... anyError_`\n\n","type":"Morph.ErrorWithDeadEnd Basics.Never -> any_"},{"name":"description","comment":" The morph's [`Description`](#Description).\n\nAdd custom ones via [`Morph.named`](#named)\n\n","type":"Morph.MorphIndependently narrow_ broaden_ -> Morph.Description"},{"name":"descriptionAndErrorToTree","comment":" Create a tree describing a given [`Error`](#Error) embedded in a given [`Description`](#Description).\n","type":"Morph.Description -> Morph.Error -> Tree.Tree { text : String.String, kind : Morph.DescriptionOrErrorKind }"},{"name":"descriptionToTree","comment":" Create a tree from the structured [`Description`](#Description)\n","type":"Morph.Description -> Tree.Tree { kind : Morph.DescriptionKind, text : String.String }"},{"name":"end","comment":" Only succeeds when there are no remaining broad input elements afterwards.\n\nThis is not required for [`Morph.toNarrow`](#toNarrow) to succeed.\n\nThe only use I can think of is when checking for a line ending:\n\n    type LineEnding\n        = LineBreak\n        | EndOfFile\n\n    lineEnding : MorphRow () Char\n    lineEnding =\n        -- always prefer a line-break before the end of the file\n        Morph.broad LineBreak\n            |> Morph.overRow\n                (Morph.choice\n                    (\\lineBreak endOfFile lineEndingChoice ->\n                        case lineEndingChoice of\n                            LineBreak ->\n                                lineBreak ()\n\n                            EndOfFile ->\n                                endOfFile ()\n                    )\n                    |> Morph.rowTry (\\() -> LineBreak) (String.Morph.only \"\\n\")\n                    |> Morph.rowTry (\\() -> EndOfFile) Morph.end\n                )\n\n","type":"Morph.MorphRow () broadElement_"},{"name":"errorMap","comment":" Change the potential [`Error`](#Error). This is usually used with either\n\n  - [`deadEndNever : ErrorWithDeadEnd Never -> any_`](#deadEndNever)\n      - allows you to for example annotate a\n        [`MorphOrError narrow broad (ErrorWithDeadEnd never_)`](#MorphOrError)\n        as\n        `MorphOrError narrow broad never_`\n  - [`deadEndMap`](#deadEndMap)\n\n","type":"(error -> errorMapped) -> Morph.MorphIndependently (beforeToNarrow -> Result.Result error narrowed) toBroad -> Morph.MorphIndependently (beforeToNarrow -> Result.Result errorMapped narrowed) toBroad"},{"name":"grab","comment":" Take what we get from [converting](#MorphRow) the next section\nand channel it back up to the [`Morph.narrow`](Morph#narrow) grouping\n","type":"(groupNarrow -> partNextBeforeToBroad) -> Morph.MorphRowIndependently partNextNarrow partNextBeforeToBroad broadElement -> Morph.MorphRowIndependently (partNextNarrow -> groupToNarrowFurther) groupNarrow broadElement -> Morph.MorphRowIndependently groupToNarrowFurther groupNarrow broadElement"},{"name":"invert","comment":" `OneToOne a b` → `OneToOne b a`\nby swapping the internal functions [`map`](#mapTo) and [`unmap`](#toBroad).\n\n    import Morph\n    import List.Morph\n\n    [ 'O', 'h', 'a', 'y', 'o' ]\n        |> Morph.mapTo (Morph.invert List.Morph.string)\n    --> \"Ohayo\"\n\n(Only for illustration.\nFirst, `mapTo (... |> invert)` is just [`toBroad ...`](#toBroad).\nSecond, the inverse [`String.Morph.list`](String-Morph#list) also exists)\n\nThis can be used to easily create a `fromX`/`toX` pair\n\n    import Emptiable exposing (Emptiable)\n    import List.NonEmpty\n    import Stack exposing (Stacked)\n\n    stackFromListNonEmpty :\n        MorphIndependently\n            (List.NonEmpty.NonEmpty element\n             -> Result error_ (Emptiable (Stacked element) never_)\n            )\n            (Emptiable (Stacked element) Never\n             -> List.NonEmpty.NonEmpty element\n            )\n    stackFromListNonEmpty =\n        toListNonEmpty |> Morph.invert\n\n    listNonEmptyFromStack :\n        MorphIndependently\n            (Emptiable (Stacked element) Never\n             -> Result error_ (List.NonEmpty.NonEmpty element)\n            )\n            (List.NonEmpty.NonEmpty element\n             -> Emptiable (Stacked element) never_\n            )\n    listNonEmptyFromStack =\n        Morph.oneToOne Stack.toTopBelow Stack.fromTopBelow\n\n","type":"Morph.MorphIndependently (beforeMap -> Result.Result (Morph.ErrorWithDeadEnd Basics.Never) mapped) (beforeUnmap -> unmapped) -> Morph.MorphIndependently (beforeUnmap -> Result.Result error_ unmapped) (beforeMap -> mapped)"},{"name":"keep","comment":" A [`Morph`](#Morph) that doesn't transform anything.\nAny possible input stays the same in both directions.\n\nSame as writing:\n\n  - [`oneToOne`](#oneToOne)`identity identity`\n  - [`toggle`](#toggle)`identity` when broad and narrow types match\n  - `custom ... { toBroad = identity, toNarrow = Ok }`\n\n","type":"Morph.MorphIndependently (narrow -> Result.Result error_ narrow) (broad -> broad)"},{"name":"mapTo","comment":" Convert `unmapped -> mapped`. This can never fail.\n\n    import List.Morph\n\n    \"3456\" |> Morph.mapTo List.Morph.string\n    --> [ '3', '4', '5', '6' ]\n\nIf your morph is fallible, you'll get a compiler error.\nIn that case, use [`Morph.toNarrow`](#toNarrow) to get a `Result` with a possible error.\n\n","type":"Morph.MorphIndependently (unmapped -> Result.Result (Morph.ErrorWithDeadEnd Basics.Never) mapped) broaden_ -> unmapped -> mapped"},{"name":"match","comment":" Require values to be present next to continue but ignore the result.\nOn the parsing side, this is often called \"skip\" or \"drop\", `elm/parser` uses `|.`\n\n    import String.Morph\n    import List.Morph\n    import Morph exposing (match, grab)\n    import AToZ.Morph\n    import AToZ exposing (AToZ(..))\n\n    -- parse a simple email, but we're only interested in the username\n    \"user@example.com\"\n        |> Morph.toNarrow\n            (Morph.narrow (\\userName -> { username = userName })\n                |> grab .username\n                    (Morph.whilePossible (AToZ.Morph.lowerChar |> Morph.one))\n                |> match (String.Morph.only \"@\")\n                |> match\n                    (broad [ E, X, A, M, P, L, E ]\n                        |> Morph.overRow\n                            (Morph.whilePossible (AToZ.Morph.lowerChar |> Morph.one))\n                    )\n                |> match (String.Morph.only \".com\")\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok { username = [ U, S, E, R ] }\n\n[`broad`](#broad) `... |>` [`Morph.overRow`](Morph#overRow) is cool:\nwhen multiple kinds of input can be dropped,\nit allows choosing a default possibility for building.\n\n","type":"Morph.MorphRow () broadElement -> Morph.MorphRowIndependently groupNarrow groupNarrowAssemble broadElement -> Morph.MorphRowIndependently groupNarrow groupNarrowAssemble broadElement"},{"name":"named","comment":" Describe what you want to narrow to.\nThis will make errors and descriptions easier to understand.\n\nA good rule of thumb is to at least add a [`Morph.named`](#named) to every morph _declaration_.\nMore `named` = •ᴗ•.\n\n    import Morph exposing (MorphRow, match, grab)\n    import List.Morph\n    import String.Morph\n    import Int.Morph\n    import Integer.Morph\n    -- from lue-bird/elm-no-record-type-alias-constructor-function\n    import RecordWithoutConstructorFunction exposing (RecordWithoutConstructorFunction)\n\n    type alias Point =\n        -- makes `Point` function unavailable:\n        RecordWithoutConstructorFunction\n            { x : Int\n            , y : Int\n            }\n\n    point : MorphRow Point Char\n    point =\n        Morph.named \"point\"\n            (Morph.narrow (\\x y -> { x = x, y = y })\n                |> match (String.Morph.only \"(\")\n                |> grab .x (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n                |> match (String.Morph.only \",\")\n                |> grab .y (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n                |> match (String.Morph.only \")\")\n            )\n\n    \"(12,34)\"\n        |> Morph.toNarrow\n            (point\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok { x = 12, y = 34 }\n\nEspecially for [`oneToOne`](#oneToOne) etc,\nadding a description doesn't really add value\nas users often don't need to know that you for example converted a [stack to a list](List-Morph#stack)\n\n","type":"String.String -> Morph.MorphIndependently narrow broaden -> Morph.MorphIndependently narrow broaden"},{"name":"narrow","comment":" Doesn't consume anything and always returns the given narrow constant.\n\nFor anything composed of multiple parts,\n`narrow` first declaratively describes what you expect to get in the end,\nthen you feed it by [grabbing (taking)](#grab) what you need.\n\n    import Morph exposing (grab, match)\n    import String.Morph\n    import Integer.Morph\n    import Int.Morph\n    import List.Morph\n    -- from lue-bird/elm-no-record-type-alias-constructor-function\n    import RecordWithoutConstructorFunction exposing (RecordWithoutConstructorFunction)\n\n    type alias Point =\n        -- makes `Point` function unavailable:\n        RecordWithoutConstructorFunction\n            { x : Int\n            , y : Int\n            }\n\n    point : MorphRow Point Char\n    point =\n        Morph.narrow (\\x y -> { x = x, y = y })\n            |> grab .x (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n            |> match (String.Morph.only \",\")\n            |> grab .y (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n\n    \"12,34\"\n        |> Morph.toNarrow\n            (point |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok { x = 12, y = 34 }\n\n\n### example: infix-separated elements\n\n    Morph.narrow Stack.topBelow\n        |> grab Stack.top element\n        |> grab (Stack.removeTop >> Stack.toList)\n            (Morph.whilePossible\n                (Morph.narrow (\\separator element -> { element = element, separator = separator })\n                    |> grab .separator separator\n                    |> grab .element element\n                )\n            )\n\n\n### `Morph.narrow` anti-patterns\n\nOne example you'll run into when using other parsers is using\n\n    Morph.narrow identity\n        |> match\n            ...\n        |> match\n            ...\n        |> grab identity ...\n        |> match ...\n\nit gets pretty hard to read as you have to jump around the code to know what you're actually producing\n\n    Morph.narrow (\\fileSize -> fileSize)\n        |> ...\n        |> grab (\\fileSize -> fileSize) ...\n\nis already nicer\n\n","type":"narrowConstant -> Morph.MorphRowIndependently narrowConstant beforeToBroad_ broadElement_"},{"name":"one","comment":" [`MorphRow`](#MorphRow) from and to a single broad input.\n\n\n## `Morph.keep |> Morph.one`\n\n> ℹ️ Equivalent regular expression: `.`\n\n    import Morph\n    import List.Morph\n    import String.Morph\n\n    -- can match any character\n    \"a\"\n        |> Morph.toNarrow\n            (Morph.keep |> Morph.one |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok 'a'\n\n    \"#\"\n        |> Morph.toNarrow\n            (Morph.keep |> Morph.one |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok '#'\n\n    -- only fails if we run out of inputs\n    \"\"\n        |> Morph.toNarrow\n            (Morph.keep |> Morph.one |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"Morph.Morph narrow broadElement -> Morph.MorphRow narrow broadElement"},{"name":"oneToOne","comment":" Create a [`Morph.OneToOne`](#OneToOne)\n\n    String.Morph.toList : MorphOrError (List Char) String error_\n    String.Morph.toList =\n        Morph.oneToOne String.toList String.fromList\n\nSee the [`Morph.OneToOne`](#OneToOne) documentation for more detail\n\n","type":"(beforeMap -> mapped) -> (beforeUnmap -> unmapped) -> Morph.MorphIndependently (beforeMap -> Result.Result error_ mapped) (beforeUnmap -> unmapped)"},{"name":"oneToOneOn","comment":" Morph the structure's elements\n\n    listMapOneToOne elementMorphOneToOne =\n        oneToOneOn List.map List.map elementMorphOneToOne\n\n","type":"((elementBeforeMap -> elementMapped) -> structureBeforeMap -> structureMapped) -> ((elementBeforeUnmap -> elementUnmapped) -> structureBeforeUnmap -> structureUnmapped) -> Morph.MorphIndependently (elementBeforeMap -> Result.Result (Morph.ErrorWithDeadEnd Basics.Never) elementMapped) (elementBeforeUnmap -> elementUnmapped) -> Morph.MorphIndependently (structureBeforeMap -> Result.Result error_ structureMapped) (structureBeforeUnmap -> structureUnmapped)"},{"name":"only","comment":" Match only the specific given broad element.\n\nMake helpers for each type of constant for convenience\n\n    Char.Morph.only broadCharConstant =\n        Morph.only String.fromChar broadCharConstant\n\n","type":"(broadConstant -> String.String) -> broadConstant -> Morph.Morph () broadConstant"},{"name":"over","comment":" Chain additional [`Morph`](#Morph) step from its broad side. You can think of it as\n\n  - `<<` in the `toBroad` direction\n  - `<< Result.andThen` in the `toNarrow` direction\n\n```\nInt.Morph.integer\n    |> Morph.over Integer.Morph.value\n--: MorphValue Int\n\n-- allow any case but print them lower case\nMorph.oneToOne .letter (\\letter -> { letter = letter, case_ = AToZ.CaseLower }\n    |> Morph.over AToZ.Morph.char\n--: Morph AToZ Char\n\n-- allow any letter but always print 'f'\nMorph.broad AToZ.F\n    |> Morph.over AToZ.Morph.lowerChar\n--: Morph () Char\n\nMorph.custom \"int\"\n    { toBroad = IntExpression\n    , toNarrow =\n        \\number ->\n            case number of\n                IntExpression int ->\n                    int |> Ok\n                FloatExpression _ ->\n                    \"float\" |> Err\n    }\n    |> Morph.over Value.Morph.toAtom\n--: Morph Int (AtomOrComposed NumberExpression NumberOpExpression)\n```\n\n(For the `oneToOne .letter ...` there's a shortcut: [`AToZ.Morph.broadCase AToZ.CaseLower`](AToZ-Morph#broadCase))\n\n","type":"Morph.MorphIndependently (beforeBeforeNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) beforeToNarrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeBeforeToBroad -> beforeToBroad) -> Morph.MorphIndependently (beforeBeforeNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeBeforeToBroad -> broad)"},{"name":"overRow","comment":" Chain to an even more broad type.\n\n[`Morph.overRow`](#overRow)\nis nice to translate the narrow result your [`MorphRow`](#MorphRow) produces:\n\n    import Morph\n    import String.Morph\n    import Integer.Morph\n    import Int.Morph\n    import List.Morph\n\n    \"12\"\n        |> Morph.toNarrow\n            (Int.Morph.integer\n                |> Morph.overRow Integer.Morph.chars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok 12\n\nTry to keep [`Morph.overRow`](#overRow) filters/validations to a minimum to get\n\n  - a better error description out of the box\n  - a more descriptive and correct type\n  - building invalid values becomes impossible\n  - a morph that actually, constructively describes the format\n\n```\nimport Morph\nimport N exposing (n0, n9)\nimport String.Morph\nimport List.Morph\n\n\"2-2\"\n    |> Morph.toNarrow\n        -- two digits should be at most 9\n        -- and we're only interested in the sum\n        (N.Morph.in_ ( n0, n9 )\n            |> Morph.overRow\n                (Morph.narrow (\\a b -> a |> N.add b)\n                    |> Morph.grab (\\_ -> n0 |> N.maxTo n9) (N.Morph.inChar ( n0, n9 ))\n                    |> Morph.match (String.Morph.only \"-\")\n                    |> Morph.grab identity (N.Morph.inChar ( n0, n9 ))\n                )\n            |> Morph.rowFinish\n            |> Morph.over List.Morph.string\n        )\n--> Ok (n4 |> N.minTo n0 |> N.maxTo n9)\n```\n\nIf this example seems really obscure then I can only agree with you.\nHave a better example showing a valid use-case? → PR\n\n","type":"Morph.MorphRowIndependently beforeToNarrow beforeToBroad broadElement -> Morph.MorphIndependently (beforeToNarrow -> Result.Result Morph.Error narrow) (beforeBeforeToBroad -> beforeToBroad) -> Morph.MorphRowIndependently narrow beforeBeforeToBroad broadElement"},{"name":"part","comment":" The [`Morph`](#Morph) of the next part in [`parts`](#parts).\n\n    Morph.parts\n        ( \\nameFirst nameLast email ->\n            { nameFirst = nameFirst, nameLast = nameLast, email = email }\n        , \\nameFirst nameLast email ->\n            { nameFirst = nameFirst, nameLast = nameLast, email = email }\n        )\n        |> Morph.part \"name first\" ( .nameFirst, .nameFirst ) Morph.keep\n        |> Morph.part \"name last\" ( .nameLast, .nameLast ) Morph.keep\n        |> Morph.part \"email\" ( .email, .email ) emailMorph\n        |> Morph.finishParts\n\n","type":"String.String -> ( groupNarrow -> partNarrow, groupBroad -> partBroad ) -> Morph.MorphOrError partNarrow partBroad partError -> Morph.PartsMorphEmptiable noPartPossiblyOrNever_ (groupBroad -> Result.Result (Morph.PartsError partError) (partNarrow -> groupToNarrowFurther)) (groupNarrow -> partBroad -> groupToBroadFurther) -> Morph.PartsMorphEmptiable noPartNever_ (groupBroad -> Result.Result (Morph.PartsError partError) groupToNarrowFurther) (groupNarrow -> groupToBroadFurther)"},{"name":"parts","comment":" Assemble a group from narrow and broad [`part`](#part)s\n\nUse [`parts`](#parts)\nwhen each broad, toNarrow [`part`](#part) always has their respective counterpart\n\n    import Int.Morph\n    import Integer.Morph\n    import List.Morph\n    import Morph\n\n    ( \"4\", \"5\" )\n        |> Morph.toNarrow\n            (Morph.parts\n                ( \\x y -> { x = x, y = y }\n                , \\x y -> ( x, y )\n                )\n                |> Morph.part \"x\"\n                    ( .x, Tuple.first )\n                    (Int.Morph.integer\n                        |> Morph.overRow Integer.Morph.chars\n                        |> Morph.rowFinish\n                        |> Morph.over List.Morph.string\n                    )\n                |> Morph.part \"y\"\n                    ( .y, Tuple.second )\n                    (Int.Morph.integer\n                        |> Morph.overRow Integer.Morph.chars\n                        |> Morph.rowFinish\n                        |> Morph.over List.Morph.string\n                    )\n                |> Morph.partsFinish\n            )\n    --> Ok { x = 4, y = 5 }\n\n","type":"( narrowAssemble, broadAssemble ) -> Morph.PartsMorphEmptiable Possibly.Possibly (broad_ -> Result.Result error_ narrowAssemble) (groupNarrow_ -> broadAssemble)"},{"name":"partsFinish","comment":" Conclude a [`Morph.parts`](#parts) [`|> Morph.part`](#part) builder.\n","type":"Morph.PartsMorphEmptiable Basics.Never (beforeToNarrow -> Result.Result (Morph.PartsError (Morph.ErrorWithDeadEnd deadEnd)) narrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad)"},{"name":"recursive","comment":" Define a [`Morph`](#Morph) recursively\n\n    import Morph exposing (grab, match)\n    import Int.Morph\n    import Integer.Morph\n    import String.Morph\n    import ArraySized.Morph exposing (atLeast)\n    import ArraySized\n    import List.Morph\n    import N exposing (n1)\n\n    type IntList\n        = End\n        | Next { head : Int, tail : IntList }\n\n    intList : MorphRow IntList Char\n    intList =\n        Morph.recursive \"int list\"\n            (\\intListStep ->\n                Morph.choice\n                    (\\endVariant nextVariant intListChoice ->\n                        case intListChoice of\n                            End ->\n                                endVariant ()\n                            Next next ->\n                                nextVariant next\n                    )\n                    |> Morph.rowTry (\\() -> End) (String.Morph.only \"[]\")\n                    |> Morph.rowTry Next\n                        (Morph.narrow (\\h t -> { head = h, tail = t })\n                            |> grab .head (Int.Morph.integer |> Morph.overRow Integer.Morph.chars)\n                            |> match\n                                (broad (ArraySized.one ())\n                                    |> Morph.overRow\n                                        (atLeast n1 (String.Morph.only \" \"))\n                                )\n                            |> match (String.Morph.only \"::\")\n                            |> match\n                                (broad (ArraySized.one ())\n                                    |> Morph.overRow\n                                        (atLeast n1 (String.Morph.only \" \"))\n                                )\n                            |> grab .tail intListStep\n                        )\n                    |> Morph.choiceFinish\n            )\n\n    \"[]\"\n        |> Morph.toNarrow\n            (intList |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok End\n\n    \"1 :: []\"\n        |> Morph.toNarrow\n            (intList |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok (Next { head = 1, tail = End })\n\n    \"1 :: 2 :: []\"\n        |> Morph.toNarrow\n            (intList |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok (Next { head = 1, tail = Next { head = 2, tail = End } })\n\nWithout `recursive`, you would get an error like:\n\n>     The `intList` definition is causing a very tricky infinite loop.\n>\n>     The `intList` value depends on itself\n\nRead more about why this limitation exists\nin [compiler hint \"bad recursion\"](https://github.com/elm/compiler/blob/master/hints/bad-recursion.md#tricky-recursion)\nup until the end\n\nNote: in this example you can also simply use [`Morph.broadEnd`](#broadEnd) `|> over` [`Morph.untilNext`](#untilNext)\n\nMore notes:\n\n  - This would compile:\n\n        intList : () -> MorphRow IntList\n        intList =\n            Morph.choice ...\n                |> Morph.rowTry (\\() -> End) ...\n                |> Morph.rowTry Next\n                    (...\n                        |> grab .tail (intList ())\n                    )\n\n    This makes the compiler happy, but once we call `intList ()` somewhere in our code,\n    the Morph expands itself infinitely leading to a compiler crash 😱\n\n    > RangeError: Maximum call stack size exceeded\n\n  - Other packages like json decoders solve this problem by introducing `lazy`:\n\n        lazy :\n            (() -> MorphIndependently toNarrow toBroad)\n            -> MorphIndependently toNarrow toBroad\n        lazy morphLazy =\n            { description = morphLazy () |> description\n            , toNarrow = toNarrow (morphLazy ())\n            , toBroad = toBroad (morphLazy ())\n            }\n\n    This one doesn't crash when we call `intList` or `lazy (\\() -> intList)`\n\n    The only reason this really doesn't work with `Morph`s is that we'll get an infinitely nested\n    [`description`](#description). Using [`Morph.recursive`](#recursive),\n    each inner recursion step just refers back to the outer one.\n\n    (In principle, this would be possible btw by introducing `LazyDescription (() -> Description)`\n    but it's ugly when displaying because we don't have a structure name for the recursion)\n\n","type":"String.String -> (Morph.MorphIndependently (beforeToNarrow -> narrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (beforeToNarrow -> narrow) (beforeToBroad -> broad)) -> Morph.MorphIndependently (beforeToNarrow -> narrow) (beforeToBroad -> broad)"},{"name":"rowFinish","comment":" Final step before running a [`MorphRow`](#MorphRow),\ntransforming it into a [`Morph`](#Morph) on the full stack of input elements.\n\n    fromString =\n        Morph.toNarrow\n            (Point.morphChars\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n\nOnce you've called `|> rowFinish` there is no (performant) way to convert it back to a [`MorphRow`](#MorphRow),\nso delay it for as long as you can.\n\n","type":"Morph.MorphRow narrow broadElement -> Morph.Morph narrow (List.List broadElement)"},{"name":"rowTry","comment":" If the previous [`possibility`](#rowTry) fails\ntry this [`MorphRow`](#MorphRow).\n\n> ℹ️ Equivalent regular expression: `|`\n\n\n### example: fallback step if the previous step fails\n\n    import Morph\n    import N.Morph\n    import ArraySized.Morph exposing (atLeast)\n    import ArraySized exposing (ArraySized)\n    import N exposing (n0, n1, n2, n3, n9, N, Min, In, On, N1, N0, N9)\n    import AToZ exposing (AToZ(..))\n    import AToZ.Morph\n    import List.Morph\n\n    type AlphaNum\n        = Digits (ArraySized (N (In (On N0) (On N9))) (Min (On N1)))\n        | Letters (ArraySized AToZ (Min (On N1)))\n\n    alphaNum : MorphRow AlphaNum Char\n    alphaNum =\n        Morph.choice\n            (\\letter digit alphaNumChoice ->\n                case alphaNumChoice of\n                    Digits int ->\n                        digit int\n                    Letters char ->\n                        letter char\n            )\n            |> Morph.rowTry Letters\n                (atLeast n1 (AToZ.Morph.lowerChar |> Morph.one))\n            |> Morph.rowTry Digits\n                (atLeast n1 (N.Morph.inChar ( n0, n9 ) |> Morph.one))\n            |> Morph.choiceFinish\n\n    -- try letters, or else give me some digits\n    \"abc\"\n        |> Morph.toNarrow\n            (alphaNum |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --→ Ok (Letters (ArraySized.l3 A B C |> ArraySized.minTo n1))\n\n    -- we didn't get letters, but we still got digits\n    \"123\" |> Morph.toNarrow (alphaNum |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --→ Ok\n    --→     (Digits\n    --→         (ArraySized.l3 (n1 |> N.minTo n0 |> N.maxTo n9) (n2 |> N.minTo n0 |> N.maxTo n9) (n3 |> N.minTo n0 |> N.maxTo n9) |> ArraySized.minTo n1)\n    --→     )\n\n    -- but if we still fail, records what failed for each possibility in the error\n    \"_\"\n        |> Morph.toNarrow (alphaNum |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n\n### anti-example: using `MorphRow` for what could be a `Morph` of a single element\n\n    import Morph\n    import AToZ exposing (AToZ(..))\n    import Char.Morph\n    import String.Morph\n\n    type UnderscoreOrLetter\n        = Underscore\n        | Letter AToZ\n\n    underscoreOrLetter : MorphRow UnderscoreOrLetter Char\n    underscoreOrLetter =\n        Morph.choice\n            (\\underscoreVariant letterVariant underscoreOrLetterNarrow ->\n                case underscoreOrLetterNarrow of\n                    Underscore ->\n                        underscoreVariant ()\n                    Letter letter ->\n                        letterVariant letter\n            )\n            |> Morph.rowTry (\\() -> Underscore) (String.Morph.only \"_\")\n            |> Morph.rowTry Letter\n                (AToZ.Morph.broadCase AToZ.CaseLower\n                    |> Morph.over AToZ.Morph.char\n                    |> Morph.one\n                )\n            |> Morph.choiceFinish\n\n    -- try the first possibility\n    \"_\" |> Morph.toNarrow (underscoreOrLetter |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok Underscore\n\n    -- if it fails, try the next\n    \"a\" |> Morph.toNarrow (underscoreOrLetter |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok (Letter A)\n\n    -- if none work, records what failed for each possibility in the error\n    \"1\"\n        |> Morph.toNarrow (underscoreOrLetter |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\nbetter would be\n\n    underscoreOrLetterBetter : Morph UnderscoreOrLetter Char\n    underscoreOrLetterBetter =\n        Morph.choice\n            (\\underscoreVariant letterVariant underscoreOrLetterNarrow ->\n                case underscoreOrLetterNarrow of\n                    Underscore ->\n                        underscoreVariant ()\n                    Letter letter ->\n                        letterVariant letter\n            )\n            |> Morph.try (\\() -> Underscore) (Char.Morph.only '_')\n            |> Morph.try Letter\n                (AToZ.Morph.broadCase AToZ.CaseLower\n                    |> Morph.over AToZ.Morph.char\n                )\n            |> Morph.choiceFinish\n\n    underscoreOrLetter |> Morph.one\n\n","type":"(possibilityNarrow -> choiceNarrow) -> Morph.MorphRowIndependently possibilityNarrow possibilityBeforeToBroad broadElement -> Morph.ChoiceMorphRowEmptiable noTryPossiblyOrNever_ choiceNarrow ((possibilityBeforeToBroad -> Rope.Rope broadElement) -> choiceToBroadFurther) broadElement -> Morph.ChoiceMorphRowEmptiable never_ choiceNarrow choiceToBroadFurther broadElement"},{"name":"toBroad","comment":" Its transformation that turns `narrow` into `broad`.\nSome call it \"build\"\n","type":"Morph.MorphIndependently narrow_ broaden -> broaden"},{"name":"toNarrow","comment":" Its transformation that turns `broad` into `narrow` or an `error`.\nSome call it \"parse\"\n","type":"Morph.MorphIndependently narrow broaden_ -> narrow"},{"name":"toggle","comment":" Switch between 2 opposite representations. Examples:\n\n    toggle List.reverse\n\n    toggle not\n\n    toggle negate\n\n    toggle (\\n -> n ^ -1)\n\n    toggle Linear.opposite\n\nIf you want to allow both directions to [`MorphIndependently`](#MorphIndependently),\nopt for `oneToOne v v` instead of `toggle v`!\n\n","type":"(subject -> subject) -> Morph.MorphIndependently (subject -> Result.Result error_ subject) (subject -> subject)"},{"name":"treeToLines","comment":" Create a simple markdown-formatted message from a tree.\n","type":"Tree.Tree String.String -> List.List String.String"},{"name":"try","comment":" If the previous [`possibility`](#try) fails\ntry this [`Morph`](#Morph).\n\n> ℹ️ Equivalent regular expression: `|`\n\n    import Char.Morph\n    import AToZ.Morph\n    import Morph\n    import AToZ exposing (AToZ)\n\n    type UnderscoreOrLetter\n        = Underscore\n        | Letter AToZ\n\n    underscoreOrLetter : Morph UnderscoreOrLetter Char\n    underscoreOrLetter =\n        Morph.choice\n            (\\underscore letter underscoreOrLetterChoice ->\n                case underscoreOrLetterChoice of\n                    Underscore ->\n                        underscore ()\n                    Letter aToZ ->\n                        letter aToZ\n            )\n            |> Morph.try (\\() -> Underscore) (Char.Morph.only '_')\n            |> Morph.try Letter AToZ.Morph.lowerChar\n            |> Morph.choiceFinish\n\n    -- try the first possibility\n    '_' |> Morph.toNarrow underscoreOrLetter\n    --> Ok Underscore\n\n    -- if it fails, try the next\n    'a' |> Morph.toNarrow underscoreOrLetter\n    --> Ok (Letter AToZ.A)\n\n    -- if none work, we get the error from all possible steps\n    '1'\n        |> Morph.toNarrow underscoreOrLetter\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"(possibilityNarrow -> narrowChoice) -> Morph.MorphIndependently (possibilityBeforeNarrow -> Result.Result error possibilityNarrow) (possibilityBeforeToBroad -> possibilityBroad) -> Morph.ChoiceMorphEmptiable noTryPossiblyOrNever_ narrowChoice possibilityBeforeNarrow ((possibilityBeforeToBroad -> possibilityBroad) -> choiceToBroadFurther) error -> Morph.ChoiceMorphEmptiable noTryNever_ narrowChoice possibilityBeforeNarrow choiceToBroadFurther error"},{"name":"tryTopToBottom","comment":" Offer multiple [`Morph`](Morph#Morph) possibilities based on a given list of elements.\nWithin the possibilities tried earlier and later,\nthe one labelled `broad` will be preferred when calling [`Morph.toBroad`](#toBroad)\n\nUsually, you'll be better off with a [`Morph.choice`](#choice)\nfor an explicit tagged union `type`\nbecause you'll have the option to preserve what was [narrowed](Morph#toNarrow).\n(Remember: you can always discard that info and set a preferred option with [`Morph.broad`](Morph#broad))\n\nUse [`tryTopToBottom`](#tryTopToBottom) if you have a \"dynamic\" list of equal type morphs.\nAn example is defined variable names\n\n    import Stack\n    import String.Morph\n\n    Morph.oneToOne .info (\\info -> { tag = \"±\", info = info })\n        |> Morph.over\n            (Morph.tryTopToBottom String.Morph.only\n                (Stack.topBelow \"±\" [ \"pm\", \"plusminus\" ])\n            )\n\nThat looks really cursed. Let me try to explain:\n\nLet's call these stacked elements like `\"pm\"` and `\"plusminus\"` \"tags\".\nThey are used to build a morph for each tag, tried in the order in the stack,\nhere `String.Morph.only`.\n\nLet's call what you morph to `info`, in this case it's `()`\nbecause `String.Morph.only : MorphRow () Char` only has one valid value.\n\nNow how can the printer choose which of the tags should be used?\nSomeone needs to tell it.\nThe most generic way to do so is by setting the printer as\n\n    toBroad : { tag, info } -> broad\n\nbecause if we have the `tag`, we know which morph's printer to use!\n\nThe other direction, narrowing, is similar.\n\nSay you wanted a morph with a dynamic stack of letters.\n\n    Morph.tryTopToBottom Char.Morph.only yourLetters\n\nif we just return what the tried morph with a matching tag returns, we'd have\n\n    toNarrow : beforeToNarrow -> Result ... ()\n\nThat does not seem very useful, we want to know what possibility worked as well!\n\n    toNarrow : beforeToNarrow -> Result ... { info = (), tag = Char }\n\nNow all that's left to do is wire everything\nso that the narrow thing doesn't show the empty info:\n\n    Morph.oneToOne .tag (\\tag -> { tag = tag, info = () })\n        |> Morph.over\n            (Morph.tryTopToBottom Char.Morph.only yourLetters)\n\nThis is not exactly pretty but it's versatile at the very least.\nWe can provide default tags (see example at the top) and\nwe can set the tag as the narrow value when the `info = ()`.\n\nI welcome every question on github or @lue on slack.\n\nPerformance note: This could be optimized\nas shown in [\"Fast parsing of String Sets in Elm\" by Marcelo Lazaroni](https://lazamar.github.io/fast-parsing-of-string-sets-in-elm/)\npublished as [`dict-parser`](https://dark.elm.dmy.fr/packages/lazamar/dict-parser/latest/Parser-Dict)\n\nCurrently, such an optimized version isn't provided because\nThere is no existing Trie implementation\nthat can use non-`comparable` constrained elements\nwhich means we would have to write a complete trie implementation from scratch including the Dict part\n(`dict-parser` bases it's trie on `Dict`).\n\nHappy to merge your contributions!\n\n","type":"(tag -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) possibilityInfoNarrow) (possibilityInfoBeforeToBroad -> broad)) -> Emptiable.Emptiable (Stack.Stacked tag) Basics.Never -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) { tag : tag, info : possibilityInfoNarrow }) ({ tag : tag, info : possibilityInfoBeforeToBroad } -> broad)"},{"name":"untilLast","comment":" Keep on parsing `element`s until you encounter an `end` with no `element`s after it.\n\n    import String.Morph\n    import List.Morph\n    import AToZ.Morph\n    import AToZ exposing (..)\n\n    \"listDecoderDecoder userDecoder\"\n        |> Morph.toNarrow\n            (Morph.narrow (\\called arg -> { called = called, arg = arg })\n                |> Morph.grab .called decoderNameSubject\n                |> Morph.match (String.Morph.only \" \")\n                |> Morph.grab .arg decoderNameSubject\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok\n    -->     { called =\n    -->         ([ L, I, S, T ] |> List.map (\\l -> { case_ = AToZ.CaseLower, letter = l }))\n    -->             ++ [ { case_ = AToZ.CaseUpper, letter = D } ]\n    -->             ++ ([ E, C, O, D, E, R ] |> List.map (\\l -> { case_ = AToZ.CaseLower, letter = l }))\n    -->     , arg = [ U, S, E, R ] |> List.map (\\l -> { case_ = AToZ.CaseLower, letter = l })\n    -->     }\n\n    decoderNameSubject : MorphRow (List { case_ : AToZ.Case, letter : AToZ }) Char\n    decoderNameSubject =\n        Morph.broadEnd\n            |> Morph.overRow\n                (Morph.untilLast\n                    { end = String.Morph.only \"Decoder\"\n                    , element = AToZ.Morph.char |> Morph.one\n                    }\n                )\n\nSee [`broadEnd`](#broadEnd).\n\nFun fact: This use-case was the original motivation for creating `elm-morph`.\n\nIf you just want to repeat elements until the next `end` element regardless of whether there are\nmore elements after it, use [`untilNext`](#untilNext).\n\nIf you need to carry information to the next element (which is super rare), try [`untilLastFold`](#untilLastFold)\n\n","type":"{ element : Morph.MorphRow element broadElement, end : Morph.MorphRow end broadElement } -> Morph.MorphRow { end : end, beforeEnd : List.List element } broadElement"},{"name":"untilLastFold","comment":" Just like [`untilLast`](#untilLast):\nKeep on parsing `element`s until you encounter an `end` with no `element`s after it.\n\nIn addition, [`untilLastFold`](#untilLastFold) carries accumulated \"status\" information\nto the next element morph where you can decide how to proceed.\n\nIf that sounds complicated, then you don't need it.\nSadly some formats like midi want to save space by making you remember stuff about past events.\n\nThe fact that a morph for this case exist is pretty neat.\nBut because a few functions are involved,\nits [description](#description) can be less nice than you're used to from other structures.\nMaybe add some more context via [`Morph.named`](#named)\n\n","type":"{ element : folded -> Morph.MorphRow element broadElement, end : Morph.MorphRow end broadElement, initial : folded, fold : element -> folded -> folded } -> Morph.MorphRow { end : end, beforeEnd : List.List element } broadElement"},{"name":"untilNext","comment":" See if we have an `end`, if not, morph an `element`. Repeat.\n\nAn example: going through all declarations, which one is a decoder and for what?\n\n    import String.Morph\n    import List.Morph\n\n    \"userDecoder\"\n        |> Morph.toNarrow\n            (decoderNameSubject\n                |> Morph.rowFinish\n                |> Morph.over List.Morph.string\n            )\n    --> Ok \"user\"\n\n    decoderNameSubject : MorphRow String Char\n    decoderNameSubject =\n        String.Morph.list\n            |> Morph.over Morph.broadEnd\n            |> Morph.overRow\n                (Morph.untilNext\n                    { end =\n                        Morph.narrow ()\n                            |> match (String.Morph.only \"Decoder\")\n                            |> match Morph.end\n                    , element = Morph.keep |> Morph.one\n                    }\n                )\n\nSee [`broadEnd`](#broadEnd).\n\nNotice the [`Morph.end`](#end) which makes \"userDecoders\" fail.\n\n**If you still have input after the end element in `untilNext`, use [`untilLast`](#untilLast)**\n\nIf you need to carry information to the next element (which is super rare), try [`untilNextFold`](#untilNextFold)\n\n","type":"{ end : Morph.MorphRow endElement broadElement, element : Morph.MorphRow element broadElement } -> Morph.MorphRow { end : endElement, beforeEnd : List.List element } broadElement"},{"name":"untilNextFold","comment":" Keep on parsing `element`s until you encounter an `end` element.\nThis behavior is just like [`untilNext`](#untilNext).\n\nIn addition, [`untilNextFold`](#untilNextFold) carries accumulated \"status\" information\nto the next element morph where you can decide how to proceed.\n\nIf that sounds complicated, then you don't need it.\nSadly some formats like midi want to save space by making you remember stuff about past events.\n\nThe fact that a morph for this case exist is pretty neat.\nBut because a few functions are involved,\nits [description](#description) can be less nice than you're used to from other structures.\nMaybe add some more context via [`Morph.named`](#named)\n\n","type":"{ end : Morph.MorphRow endElement broadElement, element : folded -> Morph.MorphRow element broadElement, initial : folded, fold : element -> folded -> folded } -> Morph.MorphRow { end : endElement, beforeEnd : List.List element } broadElement"},{"name":"variant","comment":" [`Morph`](Morph#Morph) the next variant value.\nFinish with [`Morph.variantsFinish`](#variantsFinish)\n","type":"String.String -> ( narrowVariantValue -> narrowChoice, possibilityBroad -> broadChoice ) -> Morph.MorphIndependently (beforeNarrowVariantValue -> Result.Result error narrowVariantValue) (beforeBroadVariantValue -> possibilityBroad) -> Morph.VariantsMorphEmptiable noTryPossiblyOrNever_ ((beforeNarrowVariantValue -> Result.Result { index : Basics.Int, error : error } narrowChoice) -> narrowChoiceFurther) ((beforeBroadVariantValue -> broadChoice) -> broadenChoiceFurther) -> Morph.VariantsMorphEmptiable noTryNever_ narrowChoiceFurther broadenChoiceFurther"},{"name":"variants","comment":" Initialize a [variants morph](#VariantsMorphEmptiable)\nby discriminating `(` the broad`,` the narrow `)` choices,\nthen go through each [`Morph.variant`](Morph#variant),\nconcluding the builder with [`Morph.choiceFinish`](#choiceFinish)\n\nOne use case is [morphing](Morph#Morph) from and to an internal type\n\n    absoluteInternal : MorphOrError Absolute Decimal.Internal.Absolute error_\n    absoluteInternal =\n        Morph.variants\n            ( \\variantFraction variantAtLeast1 decimal ->\n                case decimal of\n                    Decimal.Internal.Fraction fractionValue ->\n                        variantFraction fractionValue\n\n                    Decimal.Internal.AtLeast1 atLeast1Value ->\n                        variantAtLeast1 atLeast1Value\n            , \\variantFraction variantAtLeast1 decimal ->\n                case decimal of\n                    Fraction fractionValue ->\n                        variantFraction fractionValue\n\n                    AtLeast1 atLeast1Value ->\n                        variantAtLeast1 atLeast1Value\n            )\n            |> Morph.variant ( Fraction, Decimal.Internal.Fraction ) fractionInternal\n            |> Morph.variant ( AtLeast1, Decimal.Internal.AtLeast1 ) atLeast1Internal\n            |> Morph.choiceFinish\n\nFor morphing choices with simple variants without values (enums),\na simple [`oneToOne`](Morph#oneToOne) also does the job\n\n    signInternal : MorphOrError Sign Sign.Internal.Sign error_\n    signInternal =\n        Morph.oneToOne\n            (\\signInternalBeforeNarrow ->\n                case signInternalBeforeNarrow of\n                    Sign.Internal.Negative ->\n                        Sign.Negative\n\n                    Sign.Internal.Positive ->\n                        Sign.Positive\n            )\n            (\\signBeforeToBroad ->\n                case signBeforeToBroad of\n                    Sign.Negative ->\n                        Sign.Internal.Negative\n\n                    Sign.Positive ->\n                        Sign.Internal.Positive\n            )\n\n","type":"( narrowByPossibility, broadenByPossibility ) -> Morph.VariantsMorphEmptiable Possibly.Possibly narrowByPossibility broadenByPossibility"},{"name":"variantsFinish","comment":" Conclude a [`Morph.variants`](Morph#variants) `|>` [`Morph.variant`](Morph#variant) builder\n","type":"Morph.VariantsMorphEmptiable Basics.Never (beforeToNarrow -> Result.Result { index : Basics.Int, error : Morph.ErrorWithDeadEnd deadEnd } narrow) broaden -> Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) broaden"},{"name":"whilePossible","comment":" Keep going until an element fails, just like [`atLeast n0`](ArraySized-Morph#atLeast).\nIf you want a to morph a `List` instead of an `ArraySized ... (Min (On N0))`, you might as well use [`whilePossible`](#whilePossible)\n\n    ArraySized.Morph.toList\n        |> Morph.overRow (ArraySized.Morph.atLeast n0)\n\nIf you need to carry information to the next element (which is super rare), try [`whilePossibleFold`](#whilePossibleFold)\n\n","type":"Morph.MorphRowIndependently elementNarrow elementBeforeToBroad broadElement -> Morph.MorphRowIndependently (List.List elementNarrow) (List.List elementBeforeToBroad) broadElement"},{"name":"whilePossibleFold","comment":" Keep going until an element fails, just like [`whilePossible`](#whilePossible)/[`atLeast n0`](ArraySized-Morph#atLeast).\nIn addition, [`whilePossibleFold`](#whilePossibleFold) carries accumulated status information\nto the next element morph where you can decide how to proceed.\n\nIf that sounds complicated, then you don't need it.\nSadly some formats like midi want to save space by making you remember stuff about past events.\n\nThe fact that a morph for this case exist is pretty neat.\nBut because a few functions are involved,\nits [description](#description) can be less nice than you're used to from other structures.\nMaybe add some more context via [`Morph.named`](#named) :)\n\n","type":"{ element : folded -> Morph.MorphRow element broadElement, fold : element -> folded -> folded, initial : folded } -> Morph.MorphRow (List.List element) broadElement"}],"binops":[]},{"name":"N.Morph","comment":" [`Morph`](Morph#Morph) for a [natural number of type `N`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bounded-nat/latest/)\n\n\n## alter\n\n@docs in_\n\n\n## transform\n\n@docs natural, bit, inChar\n\n","unions":[],"aliases":[],"values":[{"name":"bit","comment":" `Bit.O` ↔ `n0`, `Bit.I` ↔ `n1`.\n\n[Inverse](Morph#invert) of [`Bit.Morph.n`](Bit-Morph#n)\n\n","type":"Morph.MorphIndependently (Bit.Bit -> Result.Result error_ (N.N (N.In (N.Up0 minX_) (N.Up1 maxX_)))) (N.N (N.In min_ (N.Up maxTo1_ N.To N.N1)) -> Bit.Bit)"},{"name":"inChar","comment":" [`Morph`](Morph#Morph) a digit in a given range\n\n    import Morph\n    import N exposing (n1, n2, n7, n9)\n\n    '5'\n        |> Morph.toNarrow (N.Morph.inChar ( n1, n7 ))\n        |> Result.map N.toInt\n    --> Ok 5\n\n    '1'\n        |> Morph.toNarrow (N.Morph.inChar ( n2, n9 ))\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"( N.N (N.In lowerLimitMin (N.Up lowerLimitMaxToUpperLimitMin_ N.To upperLimitMin)), N.N (N.In (N.On upperLimitMin) upperLimitMax) ) -> Morph.MorphIndependently (Char.Char -> Result.Result Morph.Error (N.N (N.In lowerLimitMin upperLimitMax))) (N.N (N.In narrowMin_ (N.Up narrowMaxTo9_ N.To N.N9)) -> Char.Char)"},{"name":"in_","comment":" [`Morph`](Morph#Morph) the `N` to a more narrow range\n","type":"( N.N (N.In lowerLimitMin (N.Up lowerLimitMinX_ N.To (N.Add1 lowerLimitMinPlusX_))), N.N (N.In (N.Up upperLimitMinX_ N.To upperLimitMinPlusX_) upperLimitMax) ) -> Morph.MorphIndependently (N.N (N.In narrowMin_ narrowMax_) -> Result.Result Morph.Error (N.N (N.In lowerLimitMin upperLimitMax))) (N.N broadRange -> N.N broadRange)"},{"name":"natural","comment":" [`Morph`](Morph#Morph) from a [`Natural`](Natural#Natural).\n\n[Inverse](Morph#invert) of [`Natural.Morph.n`](Natural-Morph#n)\n\n","type":"Morph.MorphIndependently (Natural.Natural -> Result.Result error_ (N.N (N.Min (N.Up0 minX_)))) (N.N range_ -> Natural.Natural)"}],"binops":[]},{"name":"Natural","comment":" Arbitrary-size, safe natural number ≥ 0. See also [`Natural.Morph`](Natural-Morph)\n\n@docs Natural, AtLeast1\n\n\n## create\n\n@docs fromN\n\n\n## transform\n\n@docs toN\n\nThe type is rarely useful in its current state,\nas the only thing you can do is convert from and to other types.\n\nThis is enough for my use-cases\nbut feel free to PR or open an issue if you'd like to see support\nfor arbitrary-precision arithmetic like addition, multiplication, ...\n\n","unions":[{"name":"Natural","comment":" Whole number (integer) ≥ 0 of arbitrary precision.\nEither 0 directly or a positive number represented by the bit `I` followed by some\n[`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)s\n\nWhy does the type look like this?\n\nIf you need a natural number representation with a specific number of bits, you can try\n\n    ArraySized Bit (Exactly (On bitLength))\n\nFor larger numbers, where you want to allow numbers of arbitrary precision,\nonly our version can enforce that `==` always gives the correct answer,\nsince the `ArraySized` could be constructed with leading `O`s!\n\n","args":[],"cases":[["N0",[]],["AtLeast1",["Natural.AtLeast1"]]]}],"aliases":[{"name":"AtLeast1","comment":" Positive natural number, can be arbitrarily large\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { bitsAfterI : List.List Bit.Bit }"}],"values":[{"name":"fromN","comment":" Convert from a [natural number of type `N`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bounded-nat/latest/)\n","type":"N.N range_ -> Natural.Natural"},{"name":"toN","comment":" Convert to a [natural number of type `N`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bounded-nat/latest/)\n\nKeep in mind that this can overflow\nsince `N` is fixed in bit size just like `Int` while [`Natural`](#Natural) is not.\n\n","type":"Natural.Natural -> N.N (N.Min (N.Up0 minX_))"}],"binops":[]},{"name":"Natural.Morph","comment":" [`Morph`](Morph#Morph) for an [arbitrary-sized `Natural`](Natural#Natural)\n\n@docs integer, n\n\n\n## [row](Morph#MorphRow)\n\n@docs chars, bits, bitsVariableCount\n\n","unions":[],"aliases":[],"values":[{"name":"bits","comment":" [`MorphRow`](Morph#MorphRow) for a [`Natural`](Natural#Natural)\nfrom a given count of [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)s\nand with a given [endianness](https://dark.elm.dmy.fr/packages/elm/bytes/latest/Bytes#Endianness).\n\nNote that the bit count can be any number like `n7` or `n128`. Numbers greater than `n16`\ncan quickly be generated locally, see [this section in the `N` module documentation](https://dark.elm.dmy.fr/packages/lue-bird/elm-bounded-nat/latest/N#specific-numbers)\n\nFor [`toBroad`](Morph#toBroad): If the number is greater than the capacity possible with the given bit count,\nthe greatest possible value will be returned instead.\n\nTo keep the whole range → [`bitsVariableCount`](#bitsVariableCount)\n\n","type":"Bytes.Endianness -> N.N (N.In (N.Up bitCountMinX_ N.To bitCountMinPlusX_) (N.Up bitCountMaxX_ N.To bitCountMaxPlusX_)) -> Morph.MorphRow Natural.Natural Bit.Bit"},{"name":"bitsVariableCount","comment":" Unlike [`bits`](#bits) which takes a concrete bit count,\n[`bitsVariableCount`](#bitsVariableCount) can preserve any length\n","type":"Morph.MorphRow Natural.Natural Bit.Bit"},{"name":"chars","comment":" [`Natural`](Natural#Natural) [`MorphRow`](Morph#MorphRow)\n\n    import Morph\n    import List.Morph\n    import N\n    import Natural\n\n    \"123\"\n        |> Morph.toNarrow\n            (Natural.Morph.chars |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.map (Natural.toN >> N.toInt)\n    --> Ok 123\n\n    -- a negative integer is not a natural\n    \"-123\"\n        |> Morph.toNarrow\n            (Natural.Morph.chars |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n    -- a decimal number is not a natural\n    \"3.14\"\n        |> Morph.toNarrow (Natural.Morph.chars |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n    -- letters etc are not accepted\n    \"3e10\"\n        |> Morph.toNarrow (Natural.Morph.chars |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n","type":"Morph.MorphRow Natural.Natural Char.Char"},{"name":"integer","comment":" [`Morph`](Morph#Morph) to a [`Natural`](Natural#Natural)\nfrom an unsigned [`Integer`](Integer#Integer)\n","type":"Morph.Morph Natural.Natural Integer.Integer"},{"name":"n","comment":" [`Morph`](Morph#Morph) from a [fixed-size `N`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bounded-nat/latest/).\n\n[Inverse](Morph#invert) of [`N.Morph.natural`](N-Morph#natural)\n\n","type":"Morph.MorphIndependently (N.N range_ -> Result.Result error_ Natural.Natural) (Natural.Natural -> N.N (N.Min (N.Up0 minX_)))"}],"binops":[]},{"name":"Result.Morph","comment":" [`Morph`](Morph#Morph) an [`elm/core` `Result error success`](https://dark.elm.dmy.fr/packages/elm/core/latest/Result#Result)\n\n@docs toOk, toErr\n\n","unions":[],"aliases":[],"values":[{"name":"toErr","comment":" `Err error` succeeds with the `error`, `Ok` fails.\n\n    import Morph\n    import Char.Morph\n\n    Err 'Y'\n        |> Morph.toNarrow\n            (Char.Morph.only 'Y'\n                |> Morph.over Result.Morph.toErr\n            )\n    --> Ok ()\n\n    Ok [ \"Bye\", \"!\" ]\n        |> Morph.toNarrow Result.Morph.toErr\n    --> Err (Morph.DeadEnd \"ok\")\n\n","type":"Morph.MorphIndependently (Result.Result narrowError narrowSuccess_ -> Result.Result Morph.Error narrowError) (broadError -> Result.Result broadError broadSuccess_)"},{"name":"toOk","comment":" `Ok success` succeeds with the `success`, `Err error` fails with the `error`.\n\n    import Morph\n    import Char.Morph\n\n    Ok 'Y'\n        |> Morph.toNarrow\n            (Char.Morph.only 'Y'\n                |> Morph.over Result.Morph.toOk\n            )\n    --> Ok ()\n\n    Err [ \"Hiyo\", \"!\" ]\n        |> Morph.toNarrow Result.Morph.toOk\n    --> Err (Morph.DeadEnd [ \"Hiyo\", \"!\" ])\n\nIf your error type is not a `String`,\nyou will need [`|> Morph.errorMap`](Morph#errorMap) [`(Morph.deadEndMap ..your error to String..)`](Morph#deadEndMap)\nto make dead end types unify.\n\n","type":"Morph.MorphIndependently (Result.Result narrowError narrowSuccess -> Result.Result (Morph.ErrorWithDeadEnd narrowError) narrowSuccess) (broadSuccess -> Result.Result broadSuccess_ broadSuccess)"}],"binops":[]},{"name":"Set.Morph","comment":" [`Morph`](Morph) an [`elm/core` `Set element`](https://dark.elm.dmy.fr/packages/elm/core/latest/Set#Set)\n\n\n## alter\n\n@docs each\n\n\n## transform\n\n@docs list, value\n\n","unions":[],"aliases":[],"values":[{"name":"each","comment":" [`Morph`](Morph#Morph) all elements.\nOn the narrowing side all [narrowed](Morph#toNarrow) values must be `Ok`\nfor it to not result in a [`Morph.Error`](Morph#Error)\n\nIf the given element [`Morph`](Morph#Morph) is [`OneToOne`](Morph#OneToOne),\n`each` will always succeed with the type knowing it does\n\n","type":"Morph.MorphIndependently (comparableBeforeNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) comparableNarrow) (comparableBeforeToBroad -> comparableBroad) -> Morph.MorphIndependently (Set.Set comparableBeforeNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) (Set.Set comparableNarrow)) (Set.Set comparableBeforeToBroad -> Set.Set comparableBroad)"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List`\n\n    import Set\n    import Morph\n\n    [ 0, 1, 2, 3 ]\n        |> Morph.mapTo Set.Morph.list\n    --> Set.fromList [ 0, 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`List.Morph.set`](List-Morph#set)\n\n","type":"Morph.MorphIndependently (List.List comparableNarrowElement -> Result.Result error_ (Set.Set comparableNarrowElement)) (Set.Set broadElement -> List.List broadElement)"},{"name":"value","comment":" `Set` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue comparableElement -> Value.Morph.Internal.MorphValue (Set.Set comparableElement)"}],"binops":[]},{"name":"Sign","comment":" Number sign. See also [`Sign.Morph`](Sign-Morph)\n\n@docs Sign, opposite\n\n","unions":[{"name":"Sign","comment":" A number's sign\n\n  - minus-sign: `Negative`\n  - plus-sign: `Positive`\n\n","args":[],"cases":[["Negative",[]],["Positive",[]]]}],"aliases":[],"values":[{"name":"opposite","comment":" Flip the [`Sign`](#Sign) `Negative` ↔ `Positive`\n","type":"Sign.Sign -> Sign.Sign"}],"binops":[]},{"name":"Sign.Morph","comment":" [`Sign`](Sign#Sign) [`Morph`](Morph#Morph)\n\n@docs char, bit\n\n@docs maybeMinusChar\n\n","unions":[],"aliases":[],"values":[{"name":"bit","comment":" `Bit.O` `Positive`, `Bit.I` ⇄ `Negative`\n","type":"Morph.MorphOrError Sign.Sign Bit.Bit error_"},{"name":"char","comment":" [`Sign`](Sign#Sign) `'+'` or `'-'`\n","type":"Morph.Morph Sign.Sign Char.Char"},{"name":"maybeMinusChar","comment":" An optional `'-'` sign → [`Negative`](Sign#Sign),\nelse [`Positive`](Sign#Sign) without consuming `Char`s.\n","type":"Morph.MorphRow Sign.Sign Char.Char"}],"binops":[]},{"name":"Stack.Morph","comment":" [`Morph`](Morph#Morph) a [`Stack`](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack)\n\n\n## alter\n\n@docs each\n\n\n## transform\n\n@docs list, array, arraySized, string\n\n","unions":[],"aliases":[],"values":[{"name":"array","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an `Array`.\n\n    import Stack\n    import Array\n    import Morph\n\n    Array.fromList [ 0, 12, 3 ]\n        |> Morph.mapTo Stack.Morph.array\n    --> Stack.topBelow 0 [ 12, 3 ]\n    --: Emptiable (Stacked Int) Possibly\n\n[Inverse](Morph#invert) of [`Array.Morph.stack`](Array-Morph#stack)\n\n","type":"Morph.MorphIndependently (Array.Array broadElement -> Result.Result error_ (Emptiable.Emptiable (Stack.Stacked broadElement) Possibly.Possibly)) (Emptiable.Emptiable (Stack.Stacked narrowElement) Possibly.Possibly -> Array.Array narrowElement)"},{"name":"arraySized","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an [`ArraySized`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typesafe-array/latest/)\n\n    import ArraySized\n    import Morph\n    import Stack\n\n    ArraySized.l4 0 1 2 3\n        |> Morph.mapTo Stack.Morph.arraySized\n    --> Stack.topBelow 0 [ 1, 2, 3 ]\n\n[Inverse](Morph#invert) of [`ArraySized.Morph.stack`](ArraySized-Morph#stack)\n\n","type":"Morph.MorphIndependently (ArraySized.ArraySized narrowElement (N.In (N.On (N.N0OrAdd1 narrowPossiblyOrNever minFrom1_)) max_) -> Result.Result error_ (Emptiable.Emptiable (Stack.Stacked narrowElement) narrowPossiblyOrNever)) (Emptiable.Emptiable (Stack.Stacked broadElement) broadPossiblyOrNever -> ArraySized.ArraySized broadElement (N.Min (N.On (N.N0OrAdd1 broadPossiblyOrNever N.N0))))"},{"name":"each","comment":" [`Morph`](Morph#Morph) all stacked elements\n\nIf the given [`Morph`](Morph#Morph) is [`OneToOne`](Morph#OneToOne),\n[`each`](#each) will also be a [`OneToOne`](Morph#OneToOne)\n\n","type":"Morph.MorphIndependently (beforeToNarrow -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad) -> Morph.MorphIndependently (Emptiable.Emptiable (Stack.Stacked beforeToNarrow) broadEmptiablePossiblyOrNever -> Result.Result (Morph.ErrorWithDeadEnd deadEnd) (Emptiable.Emptiable (Stack.Stacked narrow) broadEmptiablePossiblyOrNever)) (Emptiable.Emptiable (Stack.Stacked beforeToBroad) narrowPossiblyOrNever -> Emptiable.Emptiable (Stack.Stacked broad) narrowPossiblyOrNever)"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List`.\n\n    import Stack\n    import Morph\n\n    [ 0, 12, 3 ]\n        |> Morph.mapTo Stack.Morph.list\n    --> Stack.topBelow 0 [ 12, 3 ]\n    --: Emptiable (Stacked Int) Possibly\n\n[Inverse](Morph#invert) of [`List.Morph.stack`](List-Morph#stack)\n\n","type":"Morph.MorphIndependently (List.List broadElement -> Result.Result error_ (Emptiable.Emptiable (Stack.Stacked broadElement) Possibly.Possibly)) (Emptiable.Emptiable (Stack.Stacked narrowElement) Possibly.Possibly -> List.List narrowElement)"},{"name":"string","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `String` to a stack of `Char`s.\n\n    import Stack\n    import Morph\n\n    \"012\" |> Morph.mapTo Stack.Morph.string\n    --> Stack.fromList [ '0', '1', '2' ]\n\n[Inverse](Morph#invert) of [`String.Morph.stack`](String-Morph#stack)\n\n","type":"Morph.MorphOrError (Emptiable.Emptiable (Stack.Stacked Char.Char) Possibly.Possibly) String.String error_"}],"binops":[]},{"name":"String.Morph","comment":" [`Morph`](Morph#Morph) for an [`elm/core` `String`](https://dark.elm.dmy.fr/packages/elm/core/latest/String#String)\n\n\n## alter\n\n@docs each\n@docs only\n\n\n### transform\n\n@docs list, stack, array, arraySized, value\n\n\n## sequence\n\n@docs sequenceMap, broadSequenceMap\n\n","unions":[],"aliases":[],"values":[{"name":"array","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an `Array Char`\n\n    import Array\n    import Morph\n\n    Array.fromList [ '0', '1', '2', '3' ]\n        |> Morph.mapTo String.Morph.array\n    --> \"0123\"\n\n[Inverse](Morph#invert) of [`Array.Morph.string`](Array-Morph#string)\n\n","type":"Morph.MorphOrError String.String (Array.Array Char.Char) error_"},{"name":"arraySized","comment":" [`Morph.OneToOne`](Morph#OneToOne) from an\n[`ArraySized`](https://dark.elm.dmy.fr/packages/lue-bird/elm-typesafe-array/latest/) of `Char`s\n\n    import ArraySized\n    import Morph\n\n    ArraySized.l4 '0' '1' '2' '3'\n        |> Morph.mapTo String.Morph.arraySized\n    --> \"0123\"\n\n[Inverse](Morph#invert) of [`ArraySized.Morph.string`](ArraySized-Morph#string)\n\n","type":"Morph.MorphIndependently (ArraySized.ArraySized Char.Char narrowRange_ -> Result.Result error_ String.String) (String.String -> ArraySized.ArraySized Char.Char (N.Min (N.Up0 broadX_)))"},{"name":"broadSequenceMap","comment":" Match broad [`MorphRow`](Morph#MorphRow)s\n(those that can always produce the same broad value)\nbased on given input elements in sequence.\n\nMore details → [`List.Morph.broadSequenceMap`](List-Morph#broadSequenceMap)\n\n","type":"(Char.Char -> Morph.MorphRow () broadElement) -> String.String -> Morph.MorphRow () broadElement"},{"name":"each","comment":" [`Morph.OneToOne`](Morph#OneToOne) each `Char` in a `String`\n\nFor fallible transformations etc,\nmorph to other structures (but generic ones) like a list first\nand use its `each` morph.\n\n","type":"Morph.OneToOne Char.Char Char.Char -> Morph.MorphOrError String.String String.String error_"},{"name":"list","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a `List Char`.\n\n    import Morph\n\n    [ '0', '1', '2', '3' ] |> Morph.mapTo String.Morph.list\n    --> \"0123\"\n\n    \"0123\" |> Morph.toBroad String.Morph.list\n    --> [ '0', '1', '2', '3' ]\n\n[Inverse](Morph#invert) of [`String.Morph.list`](String-Morph#list)\n\nTo use a [`MorphRow ... Char`](Morph#MorphRow) with a `String`,\nuse [`Morph.toNarrow`](Morph#toNarrow)/[`toBroad`](Morph#toBroad)\nwith\n\n    yourData\n        |> Morph.toNarrowOrBroad\n            (yourMorphRow\n                |> Morph.rowFinish\n                |> Morph.over String.Morph.List\n            )\n\n","type":"Morph.MorphOrError String.String (List.List Char.Char) error_"},{"name":"only","comment":" Match a specific given `String` and nothing else.\nThis is case sensitive.\n\n    import Morph\n    import List.Morph\n\n    -- match an exact text\n    \"abc\"\n        |> Morph.toNarrow\n            (String.Morph.only \"abc\" |> Morph.rowFinish |> Morph.over List.Morph.string)\n    --> Ok ()\n\n    -- case sensitive\n    \"abC\"\n        |> Morph.toNarrow\n            (String.Morph.only \"abc\" |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\n    -- if there is still input remaining, fail\n    \"abcdef\"\n        |> Morph.toNarrow\n            (String.Morph.only \"abc\" |> Morph.rowFinish |> Morph.over List.Morph.string)\n        |> Result.toMaybe\n    --> Nothing\n\nSee [`sequenceMap`](#sequenceMap), [`broadSequenceMap`](#broadSequenceMap) to control what to [morph](Morph#MorphRow) for each `Char`.\n\n","type":"String.String -> Morph.MorphRow () Char.Char"},{"name":"sequenceMap","comment":" From the chars in a given `String`,\ncreate [`MorphRow`](Morph#MorphRow)s\nthat will be run in the same order, one after the other.\n\nMore details → [`List.Morph.sequenceMap`](List-Morph#sequenceMap)\n\n","type":"(Char.Char -> Morph.MorphRow narrowElement broadElement) -> String.String -> Morph.MorphRow (List.List narrowElement) broadElement"},{"name":"stack","comment":" [`Morph.OneToOne`](Morph#OneToOne) from a\n[stack](https://dark.elm.dmy.fr/packages/lue-bird/elm-emptiness-typed/latest/Stack) of `Char`s.\n\n    import Stack\n    import Morph\n\n    Stack.topBelow '0' [ '1', '2' ]\n        |> Morph.mapTo String.Morph.stack\n    --> \"012\"\n\n[Inverse](Morph#invert) of [`Stack.Morph.string`](Stack-Morph#string)\n\n","type":"Morph.MorphOrError String.String (Emptiable.Emptiable (Stack.Stacked Char.Char) Possibly.Possibly) error_"},{"name":"value","comment":" `String` [`MorphValue`](Value-Morph#MorphValue)\n","type":"Value.Morph.Internal.MorphValue String.String"}],"binops":[]},{"name":"Tree.Morph","comment":" [`Morph`](Morph#Morph) for a [`Tree` from `zwilias/elm-rosetree`](https://dark.elm.dmy.fr/packages/zwilias/elm-rosetree/latest/)\n\n@docs value\n\n","unions":[],"aliases":[],"values":[{"name":"value","comment":" [`MorphValue`](Value-Morph#MorphValue) from a [`Tree` from `zwilias/elm-rosetree`](https://dark.elm.dmy.fr/packages/zwilias/elm-rosetree/latest/)\n","type":"Value.Morph.Internal.MorphValue a -> Value.Morph.Internal.MorphValue (Tree.Tree a)"}],"binops":[]},{"name":"Value","comment":" Generic, `case`-able elm value\n\njson encoders/decoders are pretty low-level which makes them mildly unpleasant for serialization,\nexplicitly describing **how** to serialize individual data types.\nData that has same shape could at the low level be coded differently,\nwhich means you have to spell it out explicitly each time.\n\nSwitching to a different format would also be a lot of work;\nsome low-level primitives like bools might not be supported etc.\n\nThis module has all the types and operations for these generic [`Value`](#Value)s\nwhile [`Value.Morph`](Value-Morph) and most other modules contain morphs to convert your types.\n\n@docs Value, Atom, Composed, Record, Tagged\n@docs atomKindToString, composedKindToString\n\n\n## tag\n\n@docs IndexOrName, IndexAndName\n@docs tagMap\n\n\n## an abstract concept: atom or composed\n\n@docs AtomOrComposed\n@docs composedMap, atomMap\n\n\n## oh look! other projects do similar things\n\n  - [`bundsol/`: `Boxed`](https://package.elm-lang.org/packages/bundsol/boxed/2.0.0/Boxed)\n      - 👎 no box-unbox conversion pairs\n  - [`tricycle/elm-storage`: `Storage.Value`](https://dark.elm.dmy.fr/packages/tricycle/elm-storage/latest/Storage-Value)\n      - 👎 doesn't expose the `Value` variants\n  - [`andre-dietrich/elm-generic`](https://dark.elm.dmy.fr/packages/andre-dietrich/elm-generic/latest/Generic)\n      - 👍 multiple broad formats: json, xml, yaml\n      - 👎 no encode-decode conversion pairs\n  - [`the-sett/decode-generic`](https://dark.elm.dmy.fr/packages/the-sett/decode-generic/latest/Json-Decode-Generic)\n      - 👎 no encode (so no encode-decode conversion pairs as well)\n  - [`miniBill/elm-codec`](https://dark.elm.dmy.fr/packages/miniBill/elm-codec/latest/Codec)\n  - [`MartinSStewart/elm-serialize`](https://dark.elm.dmy.fr/packages/MartinSStewart/elm-serialize/latest/)\n      - 👍 multiple broad formats: json, string (url safe), `Bytes`\n      - custom errors\n      - doesn't encode field & variant names\n          - 👎 hard to debug\n          - 👎 easy to corrupt\n          - 👍 little space\n  - [`fujiy/elm-json-convert`](https://dark.elm.dmy.fr/packages/fujiy/elm-json-convert/latest/Json-Convert)\n      - 👎 no variant converters\n  - [`prozacchiwawa/elm-json-codec`](https://dark.elm.dmy.fr/packages/prozacchiwawa/elm-json-codec/latest/JsonCodec)\n      - 👎 no variant converters\n\n","unions":[{"name":"Atom","comment":" An elm literal (that doesn't itself contain other [values](#Value))\n","args":[],"cases":[["Unit",["()"]],["Number",["Decimal.Decimal"]],["String",["String.String"]]]},{"name":"AtomOrComposed","comment":" Either\n\n  - an atom that don't itself contain values\n  - a composed structure that can itself contain recursive values\n\n","args":["atom","composed"],"cases":[["Atom",["atom"]],["Composed",["composed"]]]},{"name":"Composed","comment":" elm structure that can itself contain values\n\nOther kinds of structures should be converted to one of these.\nA tuple for example can be represented as a record.\n\nNote: To not have overly complex recursive-ish types,\na [`Value.Composed`](#Composed) _can_ describe an invalid elm value,\nfor example\n\n    List [ Unit (), String \"huh\" ]\n\n","args":["tag"],"cases":[["List",["List.List (Value.Value tag)"]],["Record",["Value.Record tag"]],["Variant",["Value.Tagged tag"]]]},{"name":"IndexOrName","comment":" Either an index Int or a name String that can identify a record part or variant.\n\nUsed as the tag in the narrowed result of a [`MorphValue`](Value-Morph#MorphValue)\n\n","args":[],"cases":[["Index",["Basics.Int"]],["Name",["String.String"]]]}],"aliases":[{"name":"IndexAndName","comment":" Both an index Int and a name String that can identify a record part or variant.\n\nUsed as the tag in the broadened result of a [`MorphValue`](Value-Morph#MorphValue)\n\n","args":[],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { index : Basics.Int, name : String.String }"},{"name":"Record","comment":" The [structure](#Composed) of a record which can hold multiple [tagged field](#Tagged) [value](#Value)s\n","args":["tag"],"type":"List.List (Value.Tagged tag)"},{"name":"Tagged","comment":" [tag](#tag)-[`Value`](#Value) pair used to represent a field or a variant\n","args":["tag"],"type":"RecordWithoutConstructorFunction.RecordWithoutConstructorFunction { tag : tag, value : Value.Value tag }"},{"name":"Value","comment":" Generic representation of any value representable in elm\n\nUse the [`MorphValue`](Value-Morph#MorphValue)s present in most `module`s of this package\nto convert a [`Value`](#Value).\n\n","args":["tag"],"type":"Value.AtomOrComposed Value.Atom (Value.Composed tag)"}],"values":[{"name":"atomKindToString","comment":" Describe the type of [`Atom`](#Atom)\n","type":"Value.Atom -> String.String"},{"name":"atomMap","comment":" If the [`AtomOrComposed`](#AtomOrComposed) is an [`Atom`](#AtomOrComposed),\nchange in a given way\n","type":"(atom -> atomMapped) -> Value.AtomOrComposed atom composed -> Value.AtomOrComposed atomMapped composed"},{"name":"composedKindToString","comment":" Describe the type of [`Composed`](#Composed)\n","type":"Value.Composed tag_ -> String.String"},{"name":"composedMap","comment":" If the [`AtomOrComposed`](#AtomOrComposed) is a [`Composed`](#AtomOrComposed),\nchange in a given way\n","type":"(composed -> composedMapped) -> Value.AtomOrComposed atom composed -> Value.AtomOrComposed atom composedMapped"},{"name":"tagMap","comment":" Reduce the amount of tag information of the [`Value`](#Value)\n","type":"(tag -> tagMapped) -> Value.Value tag -> Value.Value tagMapped"}],"binops":[]},{"name":"Value.Morph","comment":" [Morph](Morph#Morph) your types over a [generic, `case`-able elm value](Value)\n\n@docs MorphValue\n@docs unit\n\nBasically every `module` here has a [`MorphValue`](#MorphValue),\nfor example\n\n  - [`Integer.Morph`](Integer-Morph)\n  - [`Decimal.Morph`](Decimal-Morph)\n  - [`String.Morph`](String-Morph)\n  - [`Maybe.Morph`](Maybe-Morph)\n  - [`List.Morph`](List-Morph)\n  - [`Dict.Morph`](Dict-Morph)\n  - [`Set.Morph`](Set-Morph)\n  - [`Array.Morph`](Array-Morph)\n\nof course you can combine them to reach other structures,\nlike\n\n    Natural.Morph.integer\n        |> Morph.over Integer.Morph.value\n\nfor a [`Natural`](Natural#Natural)\n\n\n## grouping\n\n@docs MorphValueGroupEmptiable, PartsError\n@docs group, part, groupFinish\n\n\n## choice\n\nvariant union [`MorphValue`](#MorphValue)\n\n  - start with [`Morph.choice`](Morph#choice)\n  - add each [`|> Value.Morph.variant`](#variant)\n  - complete with [`Value.Morph.choiceFinish`](#choiceFinish)\n\n@docs variant, choiceFinish\n\n\n## tag\n\n@docs eachTag, descriptive\n\n\n## spin your own\n\nbuild on existing ones\n\n    {-| `Posix` `MorphValue`\n    -}\n    posixValue : MorphValue Posix\n    posixValue =\n        Morph.named \"posix\"\n            (Morph.oneToOne\n                Time.posixToMillis\n                Time.millisToPosix\n                |> Morph.over Int.Morph.integer\n                |> Morph.over Integer.Morph.value\n            )\n\nor define new atoms, composed structures, ... (↓ are used by [`Json`](Json) for example)\n\n@docs toAtom, toComposed\n\n\n## supported default broad formats\n\n@docs bits, json\n\nfrom [`Json`](Json)\n\n  - [`Json.Morph.jsValueMagic`](Json-Morph#jsValueMagic)\n  - [`Json.Morph.string`](Json-Morph#string)\n\n","unions":[{"name":"PartsError","comment":" What can go wrong while narrowing to a [`Record`](Value#Record)\n","args":[],"cases":[["TagsMissing",["Emptiable.Emptiable (Stack.Stacked Basics.Int) Basics.Never"]],["ValueError",["{ index : Basics.Int, error : Morph.Error }"]]]}],"aliases":[{"name":"MorphValue","comment":" [`Morph`](Morph#Morph) between a given narrow value\nand a [generic value](Value#Value)\n\nThe way it's set up, it allows build up tags as both [`IndexAndName`](Value#IndexAndName)\nwhich means you can sometimes choose which one yuo want to display for a more broad format. See [`eachTag`](#eachTag)\n\n","args":["narrow"],"type":"Morph.MorphIndependently (Value.Value Value.IndexOrName -> Result.Result Morph.Error narrow) (narrow -> Value.Value Value.IndexAndName)"},{"name":"MorphValueGroupEmptiable","comment":" possibly incomplete step from and to a [`Record`](Value#Record)\n\nbuilding:\n\n  - start with [`group`](#group)\n  - continue with [`|> part`](#part)\n  - finish with [`|> groupFinish`](#groupFinish)\n\n","args":["noPartPossiblyOrNever","groupNarrow","groupNarrowFurther"],"type":"Morph.PartsMorphEmptiable noPartPossiblyOrNever (Value.Record Value.IndexOrName -> Result.Result Value.Morph.PartsError groupNarrowFurther) (groupNarrow -> Value.Record Value.IndexAndName)"}],"values":[{"name":"bits","comment":" [`MorphRow`](Morph#MorphRow) from [`Bit`](https://dark.elm.dmy.fr/packages/lue-bird/elm-bits/latest/Bit)s.\n\nExample chain converting to [`Bytes`](https://dark.elm.dmy.fr/packages/elm/bytes/latest/)\n\n    yourTypeMorphValue\n        |> Morph.overRow Value.Morph.bits\n        |> Morph.over List.Morph.bytes\n\n","type":"Morph.MorphRowIndependently (Value.Value Value.IndexOrName) (Value.Value Value.IndexAndName) Bit.Bit"},{"name":"choiceFinish","comment":" Conclude a [`Morph.choice`](Morph#choice) [`|> Value.Morph.variant`](#variant) builder.\n","type":"Morph.ChoiceMorphEmptiable Basics.Never choiceNarrow (Value.Tagged Value.IndexOrName) (choiceNarrow -> Value.Tagged Value.IndexAndName) Morph.Error -> Value.Morph.MorphValue choiceNarrow"},{"name":"descriptive","comment":" with readable names. Use in combination with [`eachTag`](#eachTag)\n\n  - part tag = name given to the [`part` `MorphValue`](#part)\n  - variant tag = name given to the [`variant` `MorphValue`](#variant)\n  - →\n      - readable by humans\n      - readable by other tools\n      - debuggable\n      - shuffling [`Value.Morph.part`](#part) order → no change\n      - renaming [`Value.Morph.part`](#part)s → breaking change\n\nAnother option to morph tags is [`Json.Morph.compact`](Json-Morph#compact)\n\n","type":"Morph.MorphIndependently (String.String -> Result.Result error_ Value.IndexOrName) (Value.IndexAndName -> String.String)"},{"name":"eachTag","comment":" [`Morph.OneToOne`](Morph#OneToOne) the tags of a [`Value`](Value#Value).\n\n  - From one side, a tag will contain all the information that is available,\n    namely [`IndexAndName`](Value#IndexAndName). Your specified morph can choose one,\n    maybe even formatted in some way\n\n  - From the other side, a tag will come as what you chose/formatted.\n    Now it's your jon to recreate either an [`IndexOrName`](Value#IndexOrName)\n\nThe simplest such tag morph is [`descriptive`](#descriptive), which is simply\n\n    Morph.oneToOne Value.Name .name\n\nWe keep only the `.name` and we reconstruct any tag as a name.\n\nA more complex example is [`Json.Morph.compact`](Json-Morph#compact)\n\n    Morph.oneToOne\n        (\\tag ->\n            case tag |> String.uncons of\n                Just ( 'a', tagAfterA ) ->\n                    case tagAfterA |> String.toInt of\n                        Just index ->\n                            index |> Value.Index\n                        ...\n        )\n        (\\tag -> \"a\" ++ (tag.index |> String.fromInt))\n\nWe keep the `.index` but prefixed with \"a\" to make it a field name.\nWhen recovering, we have to drop the \"a\" and then extract the index again.\nFor all the cases where extracting fails, it's usually nice to just return them as a `Value.Name`\nsince we do actually know how to decode only based on name.\n\nAn example chain that uses [`eachTag`](#eachTag) to decode a project to a compact [`Json.Encode.Value`](Json-Morph#JsValueMagic):\n\n    Project.Morph.value\n        |> Morph.over (Value.Morph.eachTag Json.Morph.compact)\n        |> Morph.over Value.Morph.json\n        |> Morph.over Json.Morph.jsValueMagic\n\n","type":"Morph.MorphIndependently (tagBeforeMap -> Result.Result (Morph.ErrorWithDeadEnd Basics.Never) tagMapped) (tagBeforeUnmap -> tagUnmapped) -> Morph.MorphIndependently (Value.Value tagBeforeMap -> Result.Result (Morph.ErrorWithDeadEnd never_) (Value.Value tagMapped)) (Value.Value tagBeforeUnmap -> Value.Value tagUnmapped)"},{"name":"group","comment":" Start assembling multiple parts.\n\nContinue with [`|> part`](#part) and after you're done, [`|> groupFinish`](#groupFinish).\n\nAn example translated from [`elm/json`](https://dark.elm.dmy.fr/packages/elm/json/latest/)\n\n    import Decimal exposing (Decimal)\n    import Decimal.Morph\n    import RecordWithoutConstructorFunction exposing (RecordWithoutConstructorFunction)\n    import String.Morph\n    import Value\n\n    type alias Cause =\n        -- from lue-bird/elm-no-record-type-alias-constructor-function\n        RecordWithoutConstructorFunction\n            { name : String\n            , percent : Decimal\n            , per100k : Decimal\n            }\n\n    value : MorphValue Cause\n    value =\n        Value.Morph.group\n            (\\name percent per100k ->\n                { name = name, percent = percent, per100k = per100k }\n            )\n            |> Value.Morph.part ( .name, \"name\" ) String.Morph.value\n            |> Value.Morph.part ( .percent, \"percent\" ) Decimal.Morph.value\n            |> Value.Morph.part ( .per100k, \"per100k\" ) Decimal.Morph.value\n            |> Value.Morph.groupFinish\n\nAnother example for tuples\n\n    {-| `( ..., ... )` `MorphValue`\n\n    Just use a record with descriptive names instead!\n\n    -}\n    tuple2 :\n        ( Morph part0\n        , Morph part1\n        )\n        -> Morph ( part0, part1 )\n    tuple2 ( part0Morph, part1Morph ) =\n        Morph.named \"2-tuple\"\n            (Value.Morph.group\n                (\\part0 part1 -> ( part0, part1 ))\n                |> Value.Morph.part ( Tuple.first, \"part0\" ) part0Morph\n                |> Value.Morph.part ( Tuple.second, \"part1\" ) part1Morph\n                |> Value.Morph.groupFinish\n            )\n\n    {-| `( ..., ..., ... )` `MorphValue`\n\n    Just use a record with descriptive names instead!\n\n    -}\n    tuple3 :\n        ( Morph part0\n        , Morph part1\n        , Morph part2\n        )\n        -> Morph ( part0, part1, part2 )\n    tuple3 ( part0Morph, part1Morph, part2Morph ) =\n        Morph.named \"3-tuple\"\n            (Value.Morph.group\n                (\\part0 part1 part2 -> ( part0, part1, part2 ))\n                |> Value.Morph.part ( \\( part0, _, _ ) -> part0, \"part0\" ) part0Morph\n                |> Value.Morph.part ( \\( _, part1, _ ) -> part1, \"part1\" ) part1Morph\n                |> Value.Morph.part ( \\( _, _, part2 ) -> part2, \"part2\" ) part2Morph\n                |> Value.Morph.groupFinish\n            )\n\n","type":"groupNarrowAssemble -> Value.Morph.MorphValueGroupEmptiable Possibly.Possibly groupNarrow_ groupNarrowAssemble"},{"name":"groupFinish","comment":" Conclude the [`Value.Morph.group`](#group) [`|> Value.Morph.part`](#part) builder\n","type":"Value.Morph.MorphValueGroupEmptiable Basics.Never record record -> Value.Morph.MorphValue record"},{"name":"json","comment":" [`Morph.OneToOne`](Morph#OneToOne) from [`Json`](Json#Json)\n\n[Inverse](Morph#invert) of [`Json.Morph.value`](Json-Morph#value)\n\n","type":"Morph.MorphOrError (Value.Value String.String) Json.Json error_"},{"name":"part","comment":" Continue a group assembly [`MorphValue`](#MorphValue).\n\nFor example to morph a name String field, add\n\n    |> Value.Morph.part ( .name, \"name\" ) String.Morph.value\n\nOnce you've assembled all parts, end the builder with [`groupFinish`](#groupFinish).\n\n","type":"( group -> partValueNarrow, String.String ) -> Value.Morph.MorphValue partValueNarrow -> Value.Morph.MorphValueGroupEmptiable noPartPossiblyOrNever_ group (partValueNarrow -> groupNarrowFurther) -> Value.Morph.MorphValueGroupEmptiable noPartNever_ group groupNarrowFurther"},{"name":"toAtom","comment":" [`Morph`](Morph#Morph) to a [`AtomOrComposed`](Value#AtomOrComposed)'s atom if possible\n","type":"Morph.MorphIndependently (Value.AtomOrComposed narrowAtom narrowComposed_ -> Result.Result Morph.Error narrowAtom) (broadAtom -> Value.AtomOrComposed broadAtom broadComposed_)"},{"name":"toComposed","comment":" [`Morph`](Morph#Morph) to a [`AtomOrComposed`](Value#AtomOrComposed)'s composed if possible\n","type":"Morph.MorphIndependently (Value.AtomOrComposed narrowAtom_ narrowComposed -> Result.Result Morph.Error narrowComposed) (broadComposed -> Value.AtomOrComposed broadAtom_ broadComposed)"},{"name":"unit","comment":" `()` [`MorphValue`](#MorphValue)\n\nUsed in when [morphing](Value-Morph#MorphValue) a [variant](#variant)\nwith 0 attached values.\n\n","type":"Value.Morph.MorphValue ()"},{"name":"variant","comment":" Describe another variant [`MorphValue`](#MorphValue)\n\nWhen you're done, end the builder with [`|> Value.Morph.choiceFinish`](#choiceFinish)\n\n    type User\n        = Guest GuestData\n        | SignedIn SignedInData\n\n    value : MorphValue User\n    value =\n        Morph.choice\n            (\\variantGuest variantSignedIn user ->\n                case user of\n                    Guest guest ->\n                        variantGuest guest\n\n                    SignedIn signedIn ->\n                        variantSignedIn signedIn\n            )\n            |> Value.Morph.variant ( Guest, \"guest\" ) guestValue\n            |> Value.Morph.variant ( SignedIn, \"signed in\" ) signedInValue\n            |> Value.Morph.choiceFinish\n\nwhere `guestValue : MorphValue GuestData` and `signedInValue : MorphValue SignedInData`.\n\nIf a variant has no attached thing, use [`Value.Morph.unit`](#unit)\n\n    signValue : MorphValue Sign\n    signValue =\n        Morph.choice\n            (\\positive negative sign ->\n                case sign of\n                    Positive ->\n                        positive ()\n\n                    Negative ->\n                        negative ()\n            )\n            |> Value.Morph.variant ( \\() -> Positive, \"Positive\" ) Value.Morph.unit\n            |> Value.Morph.variant ( \\() -> Negative, \"Negative\" ) Value.Morph.unit\n            |> Value.Morph.choiceFinish\n\n","type":"( possibilityNarrow -> choiceNarrow, String.String ) -> Value.Morph.MorphValue possibilityNarrow -> Morph.ChoiceMorphEmptiable noTryPossiblyOrNever_ choiceNarrow (Value.Tagged Value.IndexOrName) ((possibilityNarrow -> Value.Tagged Value.IndexAndName) -> choiceToBroadFurther) Morph.Error -> Morph.ChoiceMorphEmptiable noTryNever_ choiceNarrow (Value.Tagged Value.IndexOrName) choiceToBroadFurther Morph.Error"}],"binops":[]}]