Anyone is able to create one of those.
Example Typed Tagged MetersTag ... Float
→ The right choice, as every Float is a valid description of Meters
Use the values of 2 Typeds to return a Tagged result.
type alias PrimeNumber =
Typed Checked PrimeNumberTag Public Int
prime3 : PrimeNumber
prime3 =
tag 3 |> isChecked PrimeNumber
prime5 =
tag 5 |> isChecked PrimeNumberIn another module
type alias NonPrime =
Typed Checked NonPrimeTag Public Int
fromMultiplyingPrimes : Prime -> Prime -> NonPrime
fromMultiplyingPrimes aPrime bPrime =
Typed.map2 (*) aPrime bPrime
|> isChecked NonPrimeOnly someone with access to the tag constructor is able to create one of those.
In effect, this means that you can only let "validated" data be of this type.
Example ... Checked ... NaturalNumberTag Int
→ ✓ not every Int can be called a NaturalNumber, it must be checked!
Anyone is able to access the value.
Use the values of 2 Public Typeds to return a result.
type alias Prime =
Typed Checked PrimeTag Public Int
prime3 =
tag 3 |> isChecked Prime
prime5 =
tag 5 |> isChecked PrimeAnywhere
val2 (+) prime3 prime5
--> 8
val2 Tuple.pair prime3 prime5
--> ( 3, 5 )
if val2 (<) onePrime otherPrime thenNote: Calling (==) on Typeds causes elm to crash.
This prevents users from finding out the inner value without using val or internalVal functions.
Only the ones with access to the tag constructor can access the internalVal.
Meaning that access can be limited to
module Special exposing (Special)
type alias Special =
Typed Tagged SpecialTag Internal SpecialValueChecked)Internal exposing (Tag(..))
A exposing (A)
import Internal exposing (Tag(..))
B exposing (B)
import Internal exposing (Tag(..))'exposed-modules' : [ "A", "B" ]This generally helps hiding implementation details.
type alias OptimizedList a =
Typed Checked OptimizedListTag Internal (Implementation a)
type alias Implementation a =
{ list : List a, length : Int }
toList --...If you have an Internal value, its value can't be read by users.
However, if you have the tag constructor, you can access this value.
type alias OptimizedList a =
Typed
Checked
OptimizedListTag
Internal
{ list : List a, length : Int }
type OptimizedListTag
= OptimizedList
toList =
internalVal OptimizedList >> .listTake 2 Internal values with the same tag and combine them.
type alias OptimizedList a =
Typed
Checked
OptimizedListTag
Internal
{ list : List a, length : Int }
type OptimizedListTag
= OptimizedList
equal a b =
internalVal2 (==) OptimizedList a bNote: Calling (==) on Typeds causes elm to crash.
This prevents users from finding out the inner value without using val or internalVal functions.
The smaller of 2 Typed comparable Typed values.
Typed.min three four
--> threeThe greater of 2 Typed comparable Typed values.
Typed.max three four
--> fourA Codec to serialize Typed values.
We don't trust that the values we encode still have the same promises as our Checked values.
Choose a value it can convert from & to and serialize that.
module Nat exposing (serialize)
type NatTag
= Nat
serialize =
Serialize.int
|> Typed.serializeChecked Nat
(\int ->
if int >= 0 then
Ok int
else
Err "Int was negative, so it couldn't be decoded as a Nat"
)
identity
module EfficientList exposing (serialize)
type EfficientListTag
= EfficientList
type alias EfficientList =
Typed Checked EfficientListTag
Internal { list : List a, length : Int }
serialize =
Typed.serializeChecked EfficientList
(\list ->
{ list = list
, length = List.length length
}
|> Ok
)
.list
Serialize.list
A value is wrapped in the
type Typedwith a phantomtag.A
Typed ... Meters ... Floatcan't be called aTyped ... Kilos ... Floatanymore!For
types with just 1 constructor with a value aTypedcan be a good replacement.who can construct such a value
CheckedTaggedwho can access the value
PublicInternalall promise additional type-safety.
reading types
Is saying:
TypedTagged, notCheckedPublicorInternal, the result will be the sameNote: Calling
(==)onTypeds causes elm to crash. This prevents users from finding out the inner value without usingvalorinternalValfunctions.