Maybe with the ability to know at the type level whether it exists.
import MaybeIs exposing (just)
[ just 1, just 7 ]
--: List (MaybeIs just_ number_)
|> List.map MaybeIs.value
--> [ 1, 7 ]MaybeIs alone will probably not proof any useful,
but we can build cool type-safe data structures with it:
type alias ListIs emptyOrNot a =
MaybeIs emptyOrNot ( a, List a )
type alias NotEmpty =
MaybeIs.CanBe { empty : () } Never
type alias Emptiable =
MaybeIs.CanBe { empty : () } ()
empty : ListIs Emptiable a_
cons : ListIs emptyOrNot_ a -> a -> ListIs notEmpty_ a
head : ListIs NotEmpty a -> aThis is exactly how ListIs is implemented.
Like Maybe with type level information about whether it exists. See CanBe.
A MaybeIs that certainly exists.
MaybeIs.just "you" |> MaybeIs.value
--> "you"Transform the value in the MaybeIs using a given function:
import MaybeIs exposing (just, nothing)
MaybeIs.map abs (just -3) --> just 3
MaybeIs.map abs nothing --> nothingIf all the arguments exist, combine them using a given function.
import MaybeIs exposing (just, nothing)
MaybeIs.map2 (+) (just 3) (just 4) --> just 7
MaybeIs.map2 (+) (just 3) nothing --> nothing
MaybeIs.map2 (+) nothing (just 4) --> nothingSafely extracts the value from a MaybeIs (CanBe nothingTag_ Never) value.
import MaybeIs exposing (just, MaybeIs)
just (just (just "you"))
|> MaybeIs.value
|> MaybeIs.value
|> MaybeIs.value
--> "you"
head : MaybeIs (CanBe empty_ Never) ( a, List a ) -> a
head =
MaybeIs.value >> Tuple.firstChain together many computations that may fail.
maybeString
|> MaybeIs.andThen parse
|> MaybeIs.andThen extraValidation
parse : String -> MaybeIs CanBe Parsed
extraValidation : Parsed -> MaybeIs CanBe ValidatedLazily use a fallback value if the MaybeIs is nothing.
import Dict
Dict.empty
|> Dict.get "Tom"
|> MaybeIs.fromMaybe
|> MaybeIs.withFallback (\() -> "unknown")
--> "unknown"Hint: MaybeIs.withFallback never is equivalent to MaybeIs.value.
When using CanBe ... Never for an argument:
theShorter :
ListIs (CanBe { empty : () } Never) a
-> ListIs emptyOrNot a
-> ListIs emptyOrNot a
theShorter aList bList =
if ListIs.length bList > ListIs.length aList then
bList
else
--↓ `NotEmpty` but we need `emptyOrNot`
aListto make both branches return emptyOrNot, we could use
aList |> ListType.unCons |> ListType.fromUnConsedalso known as: necessary code that nobody will understand.
aList |> MaybeIs.branchableTypeis a bit better.
💙 Found a better name? → open an issue.
CanBeis just a cleaner version of this. It has a simple type tag to makeNevervalues distinct:Remember to update the tag after renaming an alias.
Now the fun part:
Read more in the readme!