📦 A Maybe value that can be made non-empty depending on what we know – an "emptiable-able" value
import Stack exposing (Stacked)
fill : Emptiable fill Never -> fill
top : Emptiable (Stacked element) Never -> elementimport Emptiable exposing (Emptiable)
import Stack exposing (Stacked)
type alias Model =
WithoutConstructorFunction
{ searchKeyWords : Emptiable (Stacked String) Never
}where RecordWithoutConstructorFunction
stops the compiler from creating a constructor function for Model
Insert joke about life here
Emptiable.empty
|> Emptiable.map (\x -> x / 0)
--> Emptiable.emptyEmptiable that certainly exists, allowing type-safe extraction
import Emptiable exposing (filled, fill)
filled "Bami" |> fill
--> "Bami"Emptiable fill Possibly
Fuzzer
of a given fill
import Fuzz
Emptiable.fuzz Fuzz.char
|> Fuzz.examples 4
--> [ filled 'U', empty, filled 'M', empty ]Chain together operations that may return empty.
It's like calling map|>flatten:
If the argument is Never empty,
a given function takes its fill
and returns a new possibly empty value
Some call it
andThen
or flatMap
import Emptiable exposing (Emptiable, mapFlat)
emptiableString
|> mapFlat parse
|> mapFlat extraValidation
parse : ( Char, String ) -> Emptiable Parsed Possibly
extraValidation : Parsed -> Emptiable Parsed PossiblyFor any number of arguments:
and... |> ... |>mapFlat:
import Emptiable exposing (filled, mapFlat, and)
(filled 3)
|> and (filled 4)
|> and (filled 5)
|> mapFlat
(\( ( a, b ), c ) -> filled ( a, b, c ))
--> filled ( 3, 4, 5 )If the incoming food and the given argument are
filled, give a filled tuple of both fills back
If any is empty, give a Emptiable.empty back
and comes in handy when multiple arguments need to be filled
import Emptiable exposing (filled, map, and)
filled 3
|> and (filled 4)
|> and (filled 5)
|> map (\( ( a0, a1 ), a2 ) -> a0^a1 - a2^2)
--> filled 56In a nestable Emptiable:
Only keep it filled if the inner Emptiable is filled
Some call it join
import Emptiable exposing (filled)
filled (filled 1) |> Emptiable.flatten
--> filled 1
filled Emptiable.empty |> Emptiable.flatten
--> Emptiable.empty
Emptiable.empty |> Emptiable.flatten
--> Emptiable.emptySafely extract the filled content from a Emptiable fill Never
import Emptiable exposing (filled)
filled (filled (filled "Bami"))
|> Emptiable.fill
|> Emptiable.fill
|> Emptiable.fill
--> "Bami"
first : Empty ( first, others_ ) Never -> first
first =
Emptiable.fill >> Tuple.firstLazily use a fallback value if the Emptiable is empty
import Possibly exposing (Possibly(..))
import Emptiable exposing (Emptiable(..), fillElseOnEmpty)
import Dict
Dict.empty
|> Dict.get "Hannah"
|> Emptiable.fromMaybe
|> fillElseOnEmpty (\_ -> "unknown")
--> "unknown"
fill =
fillElseOnEmpty never
fatten =
fillElseOnEmptyConvert to a Maybe
Don't try to use this prematurely. Keeping type information as long as possible is always a win
Change the possiblyOrNever type
Empty PossiblyAn Empty possiblyOrNever can't be used as Empty Possibly
import Emptiable
import Possibly exposing (Possibly)
import Stack exposing (Stacked)
type alias Log =
Empty Possibly (Stacked String)
fromStack : Emptiable (Stacked String) possiblyOrNever_ -> Log
fromStack stackFilled =
stackFilled
--: `possiblyOrNever_` but we need `Possibly`
|> Emptiable.emptyAdapt (always Possible)NeverThe Never can't be unified with Possibly or a type variable
import Emptiable
import Stack exposing (Stacked)
theShorter :
Emptiable (Stacked element) Never
-> Emptiable (Stacked element) possiblyOrNever
-> Emptiable (Stacked element) possiblyOrNever
theShorter aStack bStack =
if Stack.length bStack > Stack.length aStack then
bStack
else
aStack
--: `Never` but we need `possiblyOrNever`
|> Emptiable.emptyAdapt nevermakes both branches return possiblyOrNever
📦 Like
Maybe, but able to know at type-level whetherEmptyis a possibilityEmptiableby itself probably won't be that useful, but it can make data structures type-safely non-emptiable:Go take a look at all the data structures in this package