has clause -> implements clause

This commit is contained in:
Bryce Miller 2023-05-20 07:15:30 -04:00
parent 0f289ed712
commit b1d592ec37
No known key found for this signature in database
GPG key ID: F1E97BF8DF152350
8 changed files with 142 additions and 128 deletions

View file

@ -30,7 +30,7 @@ Eq has
## for more detail.
## 5. Functions cannot be compared for structural equality, therefore Roc
## cannot derive `isEq` for types that contain functions.
isEq : a, a -> Bool | a has Eq
isEq : a, a -> Bool | a implements Eq
## Represents the boolean true and false using an opaque type.
## `Bool` implements the `Eq` ability.
@ -116,7 +116,7 @@ not : Bool -> Bool
## expect (Bool.false != Bool.false) == Bool.false
## expect "Apples" != "Oranges"
## ```
isNotEq : a, a -> Bool | a has Eq
isNotEq : a, a -> Bool | a implements Eq
isNotEq = \a, b -> structuralNotEq a b
# INTERNAL COMPILER USE ONLY: used to lower calls to `isEq` to structural

View file

@ -73,30 +73,30 @@ DecodeResult val : { result : Result val DecodeError, rest : List U8 }
## Decodes a `List U8` of utf-8 bytes where `val` is the type of the decoded
## value, and `fmt` is a [Decoder] which implements the [DecoderFormatting]
## ability
Decoder val fmt := List U8, fmt -> DecodeResult val | fmt has DecoderFormatting
Decoder val fmt := List U8, fmt -> DecodeResult val | fmt implements DecoderFormatting
## Definition of the [Decoding] ability
Decoding has
decoder : Decoder val fmt | val has Decoding, fmt has DecoderFormatting
decoder : Decoder val fmt | val implements Decoding, fmt implements DecoderFormatting
## Definition of the [DecoderFormatting] ability
DecoderFormatting has
u8 : Decoder U8 fmt | fmt has DecoderFormatting
u16 : Decoder U16 fmt | fmt has DecoderFormatting
u32 : Decoder U32 fmt | fmt has DecoderFormatting
u64 : Decoder U64 fmt | fmt has DecoderFormatting
u128 : Decoder U128 fmt | fmt has DecoderFormatting
i8 : Decoder I8 fmt | fmt has DecoderFormatting
i16 : Decoder I16 fmt | fmt has DecoderFormatting
i32 : Decoder I32 fmt | fmt has DecoderFormatting
i64 : Decoder I64 fmt | fmt has DecoderFormatting
i128 : Decoder I128 fmt | fmt has DecoderFormatting
f32 : Decoder F32 fmt | fmt has DecoderFormatting
f64 : Decoder F64 fmt | fmt has DecoderFormatting
dec : Decoder Dec fmt | fmt has DecoderFormatting
bool : Decoder Bool fmt | fmt has DecoderFormatting
string : Decoder Str fmt | fmt has DecoderFormatting
list : Decoder elem fmt -> Decoder (List elem) fmt | fmt has DecoderFormatting
u8 : Decoder U8 fmt | fmt implements DecoderFormatting
u16 : Decoder U16 fmt | fmt implements DecoderFormatting
u32 : Decoder U32 fmt | fmt implements DecoderFormatting
u64 : Decoder U64 fmt | fmt implements DecoderFormatting
u128 : Decoder U128 fmt | fmt implements DecoderFormatting
i8 : Decoder I8 fmt | fmt implements DecoderFormatting
i16 : Decoder I16 fmt | fmt implements DecoderFormatting
i32 : Decoder I32 fmt | fmt implements DecoderFormatting
i64 : Decoder I64 fmt | fmt implements DecoderFormatting
i128 : Decoder I128 fmt | fmt implements DecoderFormatting
f32 : Decoder F32 fmt | fmt implements DecoderFormatting
f64 : Decoder F64 fmt | fmt implements DecoderFormatting
dec : Decoder Dec fmt | fmt implements DecoderFormatting
bool : Decoder Bool fmt | fmt implements DecoderFormatting
string : Decoder Str fmt | fmt implements DecoderFormatting
list : Decoder elem fmt -> Decoder (List elem) fmt | fmt implements DecoderFormatting
## `record state stepField finalizer` decodes a record field-by-field.
##
@ -104,7 +104,7 @@ DecoderFormatting has
## `Skip` if the field is not a part of the decoded record.
##
## `finalizer` should produce the record value from the decoded `state`.
record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting
record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state -> Result val DecodeError) -> Decoder val fmt | fmt implements DecoderFormatting
## `tuple state stepElem finalizer` decodes a tuple element-by-element.
##
@ -113,7 +113,7 @@ DecoderFormatting has
## index passed to `stepElem` is 0-indexed.
##
## `finalizer` should produce the tuple value from the decoded `state`.
tuple : state, (state, Nat -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting
tuple : state, (state, Nat -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt | fmt implements DecoderFormatting
## Build a custom [Decoder] function. For example the implementation of
## `decodeBool` could be defined as follows;
@ -125,11 +125,11 @@ DecoderFormatting has
## ['t', 'r', 'u', 'e', ..] -> { result: Ok Bool.true, rest: List.drop bytes 4 }
## _ -> { result: Err TooShort, rest: bytes }
## ```
custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting
custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt implements DecoderFormatting
custom = \decode -> @Decoder decode
## Decode a `List U8` utf-8 bytes using a specific [Decoder] function
decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val | fmt has DecoderFormatting
decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val | fmt implements DecoderFormatting
decodeWith = \bytes, @Decoder decode, fmt -> decode bytes fmt
## Decode a `List U8` utf-8 bytes and return a [DecodeResult](#DecodeResult)
@ -141,7 +141,7 @@ decodeWith = \bytes, @Decoder decode, fmt -> decode bytes fmt
##
## actual.result == expected
## ```
fromBytesPartial : List U8, fmt -> DecodeResult val | val has Decoding, fmt has DecoderFormatting
fromBytesPartial : List U8, fmt -> DecodeResult val | val implements Decoding, fmt implements DecoderFormatting
fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt
## Decode a `List U8` utf-8 bytes and return a [Result] with no leftover bytes
@ -155,7 +155,7 @@ fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt
##
## actual == expected
## ```
fromBytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError | val has Decoding, fmt has DecoderFormatting
fromBytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError | val implements Decoding, fmt implements DecoderFormatting
fromBytes = \bytes, fmt ->
when fromBytesPartial bytes fmt is
{ result, rest } ->

View file

@ -97,13 +97,13 @@ Dict k v := {
dataIndices : List Nat,
data : List (T k v),
size : Nat,
} | k has Hash & Eq
} | k implements Hash & Eq
## Return an empty dictionary.
## ```
## emptyDict = Dict.empty {}
## ```
empty : {} -> Dict k v | k has Hash & Eq
empty : {} -> Dict k v | k implements Hash & Eq
empty = \{} ->
@Dict {
metadata: List.repeat emptySlot 8,
@ -120,7 +120,7 @@ empty = \{} ->
##
## capacityOfDict = Dict.capacity foodDict
## ```
capacity : Dict k v -> Nat | k has Hash & Eq
capacity : Dict k v -> Nat | k implements Hash & Eq
capacity = \@Dict { dataIndices } ->
cap = List.len dataIndices
@ -129,7 +129,7 @@ capacity = \@Dict { dataIndices } ->
## Return a dictionary with space allocated for a number of entries. This
## may provide a performance optimisation if you know how many entries will be
## inserted.
withCapacity : Nat -> Dict k v | k has Hash & Eq
withCapacity : Nat -> Dict k v | k implements Hash & Eq
withCapacity = \_ ->
# TODO: power of 2 * 8 and actual implementation
empty {}
@ -140,7 +140,7 @@ withCapacity = \_ ->
## Dict.single "A" "B"
## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B")
## ```
single : k, v -> Dict k v | k has Hash & Eq
single : k, v -> Dict k v | k implements Hash & Eq
single = \k, v ->
insert (empty {}) k v
@ -153,7 +153,7 @@ single = \k, v ->
## |> Dict.insert 4 "Four"
## |> Bool.isEq (Dict.fromList [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"])
## ```
fromList : List (T k v) -> Dict k v | k has Hash & Eq
fromList : List (T k v) -> Dict k v | k implements Hash & Eq
fromList = \data ->
# TODO: make this efficient. Should just set data and then set all indicies in the hashmap.
List.walk data (empty {}) (\dict, T k v -> insert dict k v)
@ -168,7 +168,7 @@ fromList = \data ->
## |> Dict.len
## |> Bool.isEq 3
## ```
len : Dict k v -> Nat | k has Hash & Eq
len : Dict k v -> Nat | k implements Hash & Eq
len = \@Dict { size } ->
size
@ -184,7 +184,7 @@ len = \@Dict { size } ->
##
## expect Dict.len clearSongs == 0
## ```
clear : Dict k v -> Dict k v | k has Hash & Eq
clear : Dict k v -> Dict k v | k implements Hash & Eq
clear = \@Dict { metadata, dataIndices, data } ->
cap = List.len dataIndices
@ -212,7 +212,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
## |> Dict.walk 0 (\count, _, qty -> count + qty)
## |> Bool.isEq 36
## ```
walk : Dict k v, state, (state, k, v -> state) -> state | k has Hash & Eq
walk : Dict k v, state, (state, k, v -> state) -> state | k implements Hash & Eq
walk = \@Dict { data }, initialState, transform ->
List.walk data initialState (\state, T k v -> transform state k v)
@ -244,7 +244,7 @@ walk = \@Dict { data }, initialState, transform ->
##
## expect someoneIsAnAdult == Bool.true
## ```
walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state | k has Hash & Eq
walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state | k implements Hash & Eq
walkUntil = \@Dict { data }, initialState, transform ->
List.walkUntil data initialState (\state, T k v -> transform state k v)
@ -259,7 +259,7 @@ walkUntil = \@Dict { data }, initialState, transform ->
## expect Dict.get dictionary 1 == Ok "Apple"
## expect Dict.get dictionary 2000 == Err KeyNotFound
## ```
get : Dict k v, k -> Result v [KeyNotFound] | k has Hash & Eq
get : Dict k v, k -> Result v [KeyNotFound] | k implements Hash & Eq
get = \@Dict { metadata, dataIndices, data }, key ->
hashKey =
createLowLevelHasher {}
@ -287,7 +287,7 @@ get = \@Dict { metadata, dataIndices, data }, key ->
## |> Dict.contains 1234
## |> Bool.isEq Bool.true
## ```
contains : Dict k v, k -> Bool | k has Hash & Eq
contains : Dict k v, k -> Bool | k implements Hash & Eq
contains = \@Dict { metadata, dataIndices, data }, key ->
hashKey =
createLowLevelHasher {}
@ -312,7 +312,7 @@ contains = \@Dict { metadata, dataIndices, data }, key ->
## |> Dict.get "Apples"
## |> Bool.isEq (Ok 12)
## ```
insert : Dict k v, k, v -> Dict k v | k has Hash & Eq
insert : Dict k v, k, v -> Dict k v | k implements Hash & Eq
insert = \@Dict { metadata, dataIndices, data, size }, key, value ->
hashKey =
createLowLevelHasher {}
@ -358,7 +358,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value ->
## |> Dict.len
## |> Bool.isEq 0
## ```
remove : Dict k v, k -> Dict k v | k has Hash & Eq
remove : Dict k v, k -> Dict k v | k implements Hash & Eq
remove = \@Dict { metadata, dataIndices, data, size }, key ->
# TODO: change this from swap remove to tombstone and test is performance is still good.
hashKey =
@ -402,7 +402,7 @@ remove = \@Dict { metadata, dataIndices, data, size }, key ->
## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true
## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {}
## ```
update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k has Hash & Eq
update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k implements Hash & Eq
update = \dict, key, alter ->
# TODO: look into optimizing by merging substeps and reducing lookups.
possibleValue =
@ -425,7 +425,7 @@ update = \dict, key, alter ->
## |> Dict.toList
## |> Bool.isEq [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"]
## ```
toList : Dict k v -> List (T k v) | k has Hash & Eq
toList : Dict k v -> List (T k v) | k implements Hash & Eq
toList = \@Dict { data } ->
data
@ -440,7 +440,7 @@ toList = \@Dict { data } ->
## |> Dict.keys
## |> Bool.isEq [1,2,3,4]
## ```
keys : Dict k v -> List k | k has Hash & Eq
keys : Dict k v -> List k | k implements Hash & Eq
keys = \@Dict { data } ->
List.map data (\T k _ -> k)
@ -455,7 +455,7 @@ keys = \@Dict { data } ->
## |> Dict.values
## |> Bool.isEq ["One","Two","Three","Four"]
## ```
values : Dict k v -> List v | k has Hash & Eq
values : Dict k v -> List v | k implements Hash & Eq
values = \@Dict { data } ->
List.map data (\T _ v -> v)
@ -483,7 +483,7 @@ values = \@Dict { data } ->
## expect
## Dict.insertAll first second == expected
## ```
insertAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
insertAll : Dict k v, Dict k v -> Dict k v | k implements Hash & Eq
insertAll = \xs, ys ->
walk ys xs insert
@ -505,7 +505,7 @@ insertAll = \xs, ys ->
##
## expect Dict.keepShared first second == first
## ```
keepShared : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
keepShared : Dict k v, Dict k v -> Dict k v | k implements Hash & Eq
keepShared = \xs, ys ->
walk
xs
@ -537,11 +537,11 @@ keepShared = \xs, ys ->
##
## expect Dict.removeAll first second == expected
## ```
removeAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
removeAll : Dict k v, Dict k v -> Dict k v | k implements Hash & Eq
removeAll = \xs, ys ->
walk ys xs (\state, k, _ -> remove state k)
swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v | k has Hash & Eq
swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v | k implements Hash & Eq
swapAndUpdateDataIndex = \@Dict { metadata, dataIndices, data, size }, removedIndex, lastIndex ->
(T key _) = listGetUnsafe data lastIndex
hashKey =
@ -605,7 +605,7 @@ nextEmptyOrDeletedHelper = \metadata, probe, offset ->
# TODO: investigate if this needs to be split into more specific helper functions.
# There is a chance that returning specific sub-info like the value would be faster.
findIndexHelper : List I8, List Nat, List (T k v), I8, k, Probe, Nat -> Result Nat [NotFound] | k has Hash & Eq
findIndexHelper : List I8, List Nat, List (T k v), I8, k, Probe, Nat -> Result Nat [NotFound] | k implements Hash & Eq
findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset ->
# For finding a value, we must search past all deleted element tombstones.
index = Num.addWrap (mul8 probe.slotIndex) offset
@ -637,7 +637,7 @@ findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset ->
# This is how we grow the container.
# If we aren't to the load factor yet, just ignore this.
# The container must have an updated size including any elements about to be inserted.
maybeRehash : Dict k v -> Dict k v | k has Hash & Eq
maybeRehash : Dict k v -> Dict k v | k implements Hash & Eq
maybeRehash = \@Dict { metadata, dataIndices, data, size } ->
cap = List.len dataIndices
maxLoadCap =
@ -650,7 +650,7 @@ maybeRehash = \@Dict { metadata, dataIndices, data, size } ->
@Dict { metadata, dataIndices, data, size }
# TODO: switch rehash to iterate data and eventually clear out tombstones as well.
rehash : Dict k v -> Dict k v | k has Hash & Eq
rehash : Dict k v -> Dict k v | k implements Hash & Eq
rehash = \@Dict { metadata, dataIndices, data, size } ->
newLen = 2 * List.len dataIndices
newDict =
@ -663,7 +663,7 @@ rehash = \@Dict { metadata, dataIndices, data, size } ->
rehashHelper newDict metadata dataIndices data 0
rehashHelper : Dict k v, List I8, List Nat, List (T k v), Nat -> Dict k v | k has Hash & Eq
rehashHelper : Dict k v, List I8, List Nat, List (T k v), Nat -> Dict k v | k implements Hash & Eq
rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index ->
when List.get oldMetadata index is
Ok md ->
@ -684,7 +684,7 @@ rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index ->
# Walked entire list, complete now.
dict
insertForRehash : Dict k v, k, Nat -> Dict k v | k has Hash & Eq
insertForRehash : Dict k v, k, Nat -> Dict k v | k implements Hash & Eq
insertForRehash = \@Dict { metadata, dataIndices, data, size }, key, dataIndex ->
hashKey =
createLowLevelHasher {}

View file

@ -47,40 +47,40 @@ interface Encode
Bool.{ Bool },
]
Encoder fmt := List U8, fmt -> List U8 | fmt has EncoderFormatting
Encoder fmt := List U8, fmt -> List U8 | fmt implements EncoderFormatting
Encoding has
toEncoder : val -> Encoder fmt | val has Encoding, fmt has EncoderFormatting
toEncoder : val -> Encoder fmt | val implements Encoding, fmt implements EncoderFormatting
EncoderFormatting has
u8 : U8 -> Encoder fmt | fmt has EncoderFormatting
u16 : U16 -> Encoder fmt | fmt has EncoderFormatting
u32 : U32 -> Encoder fmt | fmt has EncoderFormatting
u64 : U64 -> Encoder fmt | fmt has EncoderFormatting
u128 : U128 -> Encoder fmt | fmt has EncoderFormatting
i8 : I8 -> Encoder fmt | fmt has EncoderFormatting
i16 : I16 -> Encoder fmt | fmt has EncoderFormatting
i32 : I32 -> Encoder fmt | fmt has EncoderFormatting
i64 : I64 -> Encoder fmt | fmt has EncoderFormatting
i128 : I128 -> Encoder fmt | fmt has EncoderFormatting
f32 : F32 -> Encoder fmt | fmt has EncoderFormatting
f64 : F64 -> Encoder fmt | fmt has EncoderFormatting
dec : Dec -> Encoder fmt | fmt has EncoderFormatting
bool : Bool -> Encoder fmt | fmt has EncoderFormatting
string : Str -> Encoder fmt | fmt has EncoderFormatting
list : List elem, (elem -> Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
record : List { key : Str, value : Encoder fmt } -> Encoder fmt | fmt has EncoderFormatting
tuple : List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
tag : Str, List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
u8 : U8 -> Encoder fmt | fmt implements EncoderFormatting
u16 : U16 -> Encoder fmt | fmt implements EncoderFormatting
u32 : U32 -> Encoder fmt | fmt implements EncoderFormatting
u64 : U64 -> Encoder fmt | fmt implements EncoderFormatting
u128 : U128 -> Encoder fmt | fmt implements EncoderFormatting
i8 : I8 -> Encoder fmt | fmt implements EncoderFormatting
i16 : I16 -> Encoder fmt | fmt implements EncoderFormatting
i32 : I32 -> Encoder fmt | fmt implements EncoderFormatting
i64 : I64 -> Encoder fmt | fmt implements EncoderFormatting
i128 : I128 -> Encoder fmt | fmt implements EncoderFormatting
f32 : F32 -> Encoder fmt | fmt implements EncoderFormatting
f64 : F64 -> Encoder fmt | fmt implements EncoderFormatting
dec : Dec -> Encoder fmt | fmt implements EncoderFormatting
bool : Bool -> Encoder fmt | fmt implements EncoderFormatting
string : Str -> Encoder fmt | fmt implements EncoderFormatting
list : List elem, (elem -> Encoder fmt) -> Encoder fmt | fmt implements EncoderFormatting
record : List { key : Str, value : Encoder fmt } -> Encoder fmt | fmt implements EncoderFormatting
tuple : List (Encoder fmt) -> Encoder fmt | fmt implements EncoderFormatting
tag : Str, List (Encoder fmt) -> Encoder fmt | fmt implements EncoderFormatting
custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting
custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt implements EncoderFormatting
custom = \encoder -> @Encoder encoder
appendWith : List U8, Encoder fmt, fmt -> List U8 | fmt has EncoderFormatting
appendWith : List U8, Encoder fmt, fmt -> List U8 | fmt implements EncoderFormatting
appendWith = \lst, @Encoder doEncoding, fmt -> doEncoding lst fmt
append : List U8, val, fmt -> List U8 | val has Encoding, fmt has EncoderFormatting
append : List U8, val, fmt -> List U8 | val implements Encoding, fmt implements EncoderFormatting
append = \lst, val, fmt -> appendWith lst (toEncoder val) fmt
toBytes : val, fmt -> List U8 | val has Encoding, fmt has EncoderFormatting
toBytes : val, fmt -> List U8 | val implements Encoding, fmt implements EncoderFormatting
toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt

View file

@ -32,7 +32,7 @@ Hash has
## Hashes a value into a [Hasher].
## Note that [hash] does not produce a hash value itself; the hasher must be
## [complete]d in order to extract the hash value.
hash : hasher, a -> hasher | a has Hash, hasher has Hasher
hash : hasher, a -> hasher | a implements Hash, hasher implements Hasher
## Describes a hashing algorithm that is fed bytes and produces an integer hash.
##
@ -41,26 +41,26 @@ Hash has
## cryptographically-secure hashing.
Hasher has
## Adds a list of bytes to the hasher.
addBytes : a, List U8 -> a | a has Hasher
addBytes : a, List U8 -> a | a implements Hasher
## Adds a single U8 to the hasher.
addU8 : a, U8 -> a | a has Hasher
addU8 : a, U8 -> a | a implements Hasher
## Adds a single U16 to the hasher.
addU16 : a, U16 -> a | a has Hasher
addU16 : a, U16 -> a | a implements Hasher
## Adds a single U32 to the hasher.
addU32 : a, U32 -> a | a has Hasher
addU32 : a, U32 -> a | a implements Hasher
## Adds a single U64 to the hasher.
addU64 : a, U64 -> a | a has Hasher
addU64 : a, U64 -> a | a implements Hasher
## Adds a single U128 to the hasher.
addU128 : a, U128 -> a | a has Hasher
addU128 : a, U128 -> a | a implements Hasher
## Completes the hasher, extracting a hash value from its
## accumulated hash state.
complete : a -> U64 | a has Hasher
complete : a -> U64 | a implements Hasher
## Adds a string into a [Hasher] by hashing its UTF-8 bytes.
hashStrBytes = \hasher, s ->
@ -72,33 +72,33 @@ hashList = \hasher, lst ->
hash accumHasher elem
## Adds a single [Bool] to a hasher.
hashBool : a, Bool -> a | a has Hasher
hashBool : a, Bool -> a | a implements Hasher
hashBool = \hasher, b ->
asU8 = if b then 1 else 0
addU8 hasher asU8
## Adds a single I8 to a hasher.
hashI8 : a, I8 -> a | a has Hasher
hashI8 : a, I8 -> a | a implements Hasher
hashI8 = \hasher, n -> addU8 hasher (Num.toU8 n)
## Adds a single I16 to a hasher.
hashI16 : a, I16 -> a | a has Hasher
hashI16 : a, I16 -> a | a implements Hasher
hashI16 = \hasher, n -> addU16 hasher (Num.toU16 n)
## Adds a single I32 to a hasher.
hashI32 : a, I32 -> a | a has Hasher
hashI32 : a, I32 -> a | a implements Hasher
hashI32 = \hasher, n -> addU32 hasher (Num.toU32 n)
## Adds a single I64 to a hasher.
hashI64 : a, I64 -> a | a has Hasher
hashI64 : a, I64 -> a | a implements Hasher
hashI64 = \hasher, n -> addU64 hasher (Num.toU64 n)
## Adds a single I128 to a hasher.
hashI128 : a, I128 -> a | a has Hasher
hashI128 : a, I128 -> a | a implements Hasher
hashI128 = \hasher, n -> addU128 hasher (Num.toU128 n)
## Adds a single Nat to a hasher.
hashNat : a, Nat -> a | a has Hasher
hashNat : a, Nat -> a | a implements Hasher
hashNat = \hasher, n ->
isPlatform32bit =
x : Nat

View file

@ -362,7 +362,7 @@ join = \lists ->
List.walk lists (List.withCapacity totalLength) (\state, list -> List.concat state list)
contains : List a, a -> Bool | a has Eq
contains : List a, a -> Bool | a implements Eq
contains = \list, needle ->
List.any list (\x -> x == needle)
@ -1036,7 +1036,7 @@ intersperse = \list, sep ->
## is considered to "start with" an empty list.
##
## If the first list is empty, this only returns `Bool.true` if the second list is empty.
startsWith : List elem, List elem -> Bool | elem has Eq
startsWith : List elem, List elem -> Bool | elem implements Eq
startsWith = \list, prefix ->
# TODO once we have seamless slices, verify that this wouldn't
# have better performance with a function like List.compareSublists
@ -1048,7 +1048,7 @@ startsWith = \list, prefix ->
## is considered to "end with" an empty list.
##
## If the first list is empty, this only returns `Bool.true` if the second list is empty.
endsWith : List elem, List elem -> Bool | elem has Eq
endsWith : List elem, List elem -> Bool | elem implements Eq
endsWith = \list, suffix ->
# TODO once we have seamless slices, verify that this wouldn't
# have better performance with a function like List.compareSublists
@ -1078,7 +1078,7 @@ split = \elements, userSplitIndex ->
## ```
## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Z, Baz] }
## ```
splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq
splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem implements Eq
splitFirst = \list, delimiter ->
when List.findFirstIndex list (\elem -> elem == delimiter) is
Ok index ->
@ -1094,7 +1094,7 @@ splitFirst = \list, delimiter ->
## ```
## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Z, Bar], after: [Baz] }
## ```
splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq
splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem implements Eq
splitLast = \list, delimiter ->
when List.findLastIndex list (\elem -> elem == delimiter) is
Ok index ->

View file

@ -25,7 +25,7 @@ interface Set
# We should have this line above the next has.
# It causes the formatter to fail currently.
# | k has Hash & Eq
# | k implements Hash & Eq
## Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type))
## type which stores a collection of unique values, without any ordering
Set k := Dict.Dict k {}
@ -35,7 +35,7 @@ Set k := Dict.Dict k {}
},
]
isEq : Set k, Set k -> Bool | k has Hash & Eq
isEq : Set k, Set k -> Bool | k implements Hash & Eq
isEq = \xs, ys ->
if len xs != len ys then
Bool.false
@ -53,7 +53,7 @@ isEq = \xs, ys ->
##
## expect countValues == 0
## ```
empty : {} -> Set k | k has Hash & Eq
empty : {} -> Set k | k implements Hash & Eq
empty = \{} -> @Set (Dict.empty {})
## Creates a new `Set` with a single value.
@ -63,7 +63,7 @@ empty = \{} -> @Set (Dict.empty {})
##
## expect countValues == 1
## ```
single : k -> Set k | k has Hash & Eq
single : k -> Set k | k implements Hash & Eq
single = \key ->
Dict.single key {} |> @Set
@ -79,7 +79,7 @@ single = \key ->
##
## expect countValues == 3
## ```
insert : Set k, k -> Set k | k has Hash & Eq
insert : Set k, k -> Set k | k implements Hash & Eq
insert = \@Set dict, key ->
Dict.insert dict key {} |> @Set
@ -112,7 +112,7 @@ expect
##
## expect countValues == 3
## ```
len : Set k -> Nat | k has Hash & Eq
len : Set k -> Nat | k implements Hash & Eq
len = \@Set dict ->
Dict.len dict
@ -142,7 +142,7 @@ expect
## expect has10 == Bool.false
## expect has20 == Bool.true
## ```
remove : Set k, k -> Set k | k has Hash & Eq
remove : Set k, k -> Set k | k implements Hash & Eq
remove = \@Set dict, key ->
Dict.remove dict key |> @Set
@ -161,7 +161,7 @@ remove = \@Set dict, key ->
## expect hasApple == Bool.true
## expect hasBanana == Bool.false
## ```
contains : Set k, k -> Bool | k has Hash & Eq
contains : Set k, k -> Bool | k implements Hash & Eq
contains = \@Set dict, key ->
Dict.contains dict key
@ -174,7 +174,7 @@ contains = \@Set dict, key ->
##
## expect Set.toList numbers == values
## ```
toList : Set k -> List k | k has Hash & Eq
toList : Set k -> List k | k implements Hash & Eq
toList = \@Set dict ->
Dict.keys dict
@ -188,7 +188,7 @@ toList = \@Set dict ->
##
## expect Set.fromList [Pear, Apple, Banana] == values
## ```
fromList : List k -> Set k | k has Hash & Eq
fromList : List k -> Set k | k implements Hash & Eq
fromList = \list ->
initial = @Set (Dict.withCapacity (List.len list))
@ -204,7 +204,7 @@ fromList = \list ->
##
## expect Set.union set1 set2 == Set.fromList [Left, Right]
## ```
union : Set k, Set k -> Set k | k has Hash & Eq
union : Set k, Set k -> Set k | k implements Hash & Eq
union = \@Set dict1, @Set dict2 ->
Dict.insertAll dict1 dict2 |> @Set
@ -217,7 +217,7 @@ union = \@Set dict1, @Set dict2 ->
##
## expect Set.intersection set1 set2 == Set.single Left
## ```
intersection : Set k, Set k -> Set k | k has Hash & Eq
intersection : Set k, Set k -> Set k | k implements Hash & Eq
intersection = \@Set dict1, @Set dict2 ->
Dict.keepShared dict1 dict2 |> @Set
@ -231,7 +231,7 @@ intersection = \@Set dict1, @Set dict2 ->
##
## expect Set.difference first second == Set.fromList [Up, Down]
## ```
difference : Set k, Set k -> Set k | k has Hash & Eq
difference : Set k, Set k -> Set k | k implements Hash & Eq
difference = \@Set dict1, @Set dict2 ->
Dict.removeAll dict1 dict2 |> @Set
@ -254,7 +254,7 @@ difference = \@Set dict1, @Set dict2 ->
##
## expect result == 2
## ```
walk : Set k, state, (state, k -> state) -> state | k has Hash & Eq
walk : Set k, state, (state, k -> state) -> state | k implements Hash & Eq
walk = \@Set dict, state, step ->
Dict.walk dict state (\s, k, _ -> step s k)
@ -273,7 +273,7 @@ walk = \@Set dict, state, step ->
##
## expect result == FoundTheAnswer
## ```
walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state | k has Hash & Eq
walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state | k implements Hash & Eq
walkUntil = \@Set dict, state, step ->
Dict.walkUntil dict state (\s, k, _ -> step s k)