Morph for an elm/core List element
From the elements in a given List,
create MorphRows
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.choiceFinishDon'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
Match broad MorphRows
(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
--> NothingNote that textOnly is available as String.Morph.only.
Others aren't, tho, like when matching only a specific
sequence of Bits
Morph.OneToOne from a stack
import Stack
import Morph
Stack.topBelow 0 [ 12, 3 ]
|> Morph.mapTo List.Morph.stack
--> [ 0, 12, 3 ]Morph.OneToOne from an Array
import Array
import Morph
Array.fromList [ 0, 1, 2, 3 ]
|> Morph.mapTo List.Morph.array
--> [ 0, 1, 2, 3 ]Morph.OneToOne from an ArraySized
import ArraySized
import Morph
ArraySized.l4 0 1 2 3
|> Morph.mapTo List.Morph.arraySized
--> [ 0, 1, 2, 3 ]Morph.OneToOne from a String to a List Char.
Morph.OneToOne from a Set
import Set
import Morph
Set.fromList [ 0, 1, 2, 3 ]
|> Morph.mapTo List.Morph.set
--> [ 0, 1, 2, 3 ]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' } ]Morph.OneToOne from Bytes
to a list of individual bits.
Now you can morph them as a row!
List MorphValue
Morphall elements. On the narrowing side all narrowed values must beOkfor it to not result in aMorph.ErrorIf the element
MorphisOneToOne,eachwill always succeed with the type knowing it does