Morph
for an elm/core
List element
each : MorphIndependently (beforeToNarrow -> Result (Morph.ErrorWithDeadEnd deadEnd) narrow) (beforeToBroad -> broad) -> MorphIndependently (List beforeToNarrow -> Result (Morph.ErrorWithDeadEnd deadEnd) (List narrow)) (List beforeToBroad -> List broad)
Morph
all elements.
On the narrowing side all narrowed values must be Ok
for it to not result in a Morph.Error
If the element Morph
is OneToOne
,
each
will always succeed with the type knowing it does
sequenceMap : (element -> MorphRow narrow broadElement) -> List element -> MorphRow (List narrow) broadElement
From the elements in a given List
,
create MorphRow
s
that will be run in the same order, one after the other.
Some also call this "traverse" (or "for" when the arguments are flipped)
import Morph exposing (MorphRow)
import String.Morph
import AToZ
"helloTHEREcooorwhat"
|> Morph.toNarrow
(List.Morph.sequenceMap casedStringOnly [ "hello", "there", "coo", "or", "what" ]
|> Morph.rowFinish
|> Morph.over List.Morph.string
)
--> Ok [ AToZ.CaseLower, AToZ.CaseUpper, AToZ.CaseLower, AToZ.CaseLower, AToZ.CaseLower ]
casedStringOnly : String -> MorphRow AToZ.Case Char
casedStringOnly string =
Morph.choice
(\lower upper cased ->
case cased of
AToZ.CaseLower -> lower ()
AToZ.CaseUpper -> upper ()
)
|> Morph.rowTry (\() -> AToZ.CaseLower)
(String.Morph.only (string |> String.toLower))
|> Morph.rowTry (\() -> AToZ.CaseUpper)
(String.Morph.only (string |> String.toUpper))
|> Morph.choiceFinish
Don't try to be clever with this.
The usual Morph.narrow
(\... -> ...) |>
grab
-match
chain
is often more explicit, descriptive and type-safe.
Because of this, List.Morph
only exposes sequenceMap
, not sequence
,
making misuse a bit more obvious.
If each element's MorphRow
will always produce the same broad value like String.Morph.only
,
use broadSequenceMap
broadSequenceMap : (element -> MorphRow () broadElement) -> List element -> MorphRow () broadElement
Match broad MorphRow
s
(those that can always produce the same broad value)
based on given input elements in sequence.
This can get verbose, so create helpers with it where you see common patterns!
import Morph exposing (MorphRow)
import Char.Morph
import List.Morph
textOnly : String -> MorphRow () Char
textOnly stringConstant =
List.Morph.broadSequenceMap
(Char.Morph.only >> Morph.one)
(stringConstant |> String.toList)
-- Match a specific character, case sensitive
"abc"
|> Morph.toNarrow
(textOnly "abc" |> Morph.rowFinish |> Morph.over List.Morph.string)
--> Ok ()
-- It fails if it's not _exactly_ the same
"abC"
|> Morph.toNarrow
(textOnly "abc" |> Morph.rowFinish |> Morph.over List.Morph.string)
|> Result.toMaybe
--> Nothing
Note that textOnly
is available as String.Morph.only
.
Others aren't, tho, like when matching only a specific
sequence of Bit
s
stack : MorphIndependently (Emptiable (Stacked broadElement) Possibly -> Result error_ (List broadElement)) (List narrowElement -> Emptiable (Stacked narrowElement) Possibly)
Morph.OneToOne
from a stack
import Stack
import Morph
Stack.topBelow 0 [ 12, 3 ]
|> Morph.mapTo List.Morph.stack
--> [ 0, 12, 3 ]
array : MorphIndependently (Array narrowElement -> Result error_ (List narrowElement)) (List element -> Array element)
Morph.OneToOne
from an Array
import Array
import Morph
Array.fromList [ 0, 1, 2, 3 ]
|> Morph.mapTo List.Morph.array
--> [ 0, 1, 2, 3 ]
arraySized : MorphIndependently (ArraySized narrowElement narrowRange_ -> Result error_ (List narrowElement)) (List broadElement -> ArraySized broadElement (N.Min (N.Up0 broadX_)))
Morph.OneToOne
from an ArraySized
import ArraySized
import Morph
ArraySized.l4 0 1 2 3
|> Morph.mapTo List.Morph.arraySized
--> [ 0, 1, 2, 3 ]
Inverse of ArraySized.Morph.list
string : MorphOrError (List Char) String error_
Morph.OneToOne
from a String
to a List Char
.
set : MorphIndependently (Set narrowElement -> Result error_ (List narrowElement)) (List comparableBroadElement -> Set comparableBroadElement)
Morph.OneToOne
from a Set
import Set
import Morph
Set.fromList [ 0, 1, 2, 3 ]
|> Morph.mapTo List.Morph.set
--> [ 0, 1, 2, 3 ]
dict : MorphIndependently (Dict broadKey broadValue -> Result error_ (List { key : broadKey, value : broadValue })) (List { key : comparableNarrowKey, value : narrowValue } -> Dict comparableNarrowKey narrowValue)
Morph.OneToOne
from a Dict key value
to a List { key : key, value : value }
.
import Dict
import List.Morph
import Morph
Dict.empty
|> Dict.insert 0 'a'
|> Dict.insert 1 'b'
|> Morph.mapTo List.Morph.dict
--> [ { key = 0, value = 'a' }, { key = 1, value = 'b' } ]
bytes : MorphOrError (Emptiable (Stacked Bit) Possibly) Bytes error_
Morph.OneToOne
from Bytes
to a list of individual bits.
Now you can morph them as a row!
value : Value.Morph.Internal.MorphValue element -> Value.Morph.Internal.MorphValue (List element)
List
MorphValue