mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Replace Bool.isEq
with Eq.isEq
This commit is contained in:
parent
4adae7651f
commit
c618ced743
9 changed files with 40 additions and 46 deletions
|
@ -1,5 +1,5 @@
|
||||||
interface Bool
|
interface Bool
|
||||||
exposes [Bool, true, false, and, or, not, isEq, isNotEq]
|
exposes [Bool, true, false, and, or, not, isNotEq]
|
||||||
imports []
|
imports []
|
||||||
|
|
||||||
Bool := [True, False]
|
Bool := [True, False]
|
||||||
|
@ -67,21 +67,6 @@ or : Bool, Bool -> Bool
|
||||||
## Returns `Bool.false` when given `Bool.true`, and vice versa.
|
## Returns `Bool.false` when given `Bool.true`, and vice versa.
|
||||||
not : Bool -> Bool
|
not : Bool -> Bool
|
||||||
|
|
||||||
## Returns `Bool.true` if the two values are *structurally equal*, and `Bool.false` otherwise.
|
|
||||||
##
|
|
||||||
## `a == b` is shorthand for `Bool.isEq a b`
|
|
||||||
##
|
|
||||||
## Structural equality works as follows:
|
|
||||||
##
|
|
||||||
## 1. Tags are equal if they have the same tag name, and also their contents (if any) are equal.
|
|
||||||
## 2. Records are equal if all their fields are equal.
|
|
||||||
## 3. Collections ([Str], [List], [Dict], and [Set]) are equal if they are the same length, and also all their corresponding elements are equal.
|
|
||||||
## 4. [Num](Num#Num) values are equal if their numbers are equal, with one exception: if both arguments to `isEq` are *NaN*, then `isEq` returns `Bool.false`. See `Num.isNaN` for more about *NaN*.
|
|
||||||
##
|
|
||||||
## Note that `isEq` takes `'val` instead of `val`, which means `isEq` does not
|
|
||||||
## accept arguments whose types contain functions.
|
|
||||||
isEq : a, a -> Bool
|
|
||||||
|
|
||||||
## Calls [isEq] on the given values, then calls [not] on the result.
|
## Calls [isEq] on the given values, then calls [not] on the result.
|
||||||
##
|
##
|
||||||
## `a != b` is shorthand for `Bool.isNotEq a b`
|
## `a != b` is shorthand for `Bool.isNotEq a b`
|
||||||
|
|
|
@ -19,6 +19,7 @@ interface Dict
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Eq.{ Eq },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
List,
|
List,
|
||||||
Num.{ Nat },
|
Num.{ Nat },
|
||||||
|
@ -72,7 +73,9 @@ interface Dict
|
||||||
## When comparing two dictionaries for equality, they are `==` only if their both their contents and their
|
## When comparing two dictionaries for equality, they are `==` only if their both their contents and their
|
||||||
## orderings match. This preserves the property that if `dict1 == dict2`, you should be able to rely on
|
## orderings match. This preserves the property that if `dict1 == dict2`, you should be able to rely on
|
||||||
## `fn dict1 == fn dict2` also being `Bool.true`, even if `fn` relies on the dictionary's ordering.
|
## `fn dict1 == fn dict2` also being `Bool.true`, even if `fn` relies on the dictionary's ordering.
|
||||||
Dict k v := List [Pair k v]
|
Dict k v := List [Pair k v] has [Eq { isEq: dictEq }]
|
||||||
|
|
||||||
|
dictEq = \@Dict l1, @Dict l2 -> l1 == l2
|
||||||
|
|
||||||
## An empty dictionary.
|
## An empty dictionary.
|
||||||
empty : Dict k v
|
empty : Dict k v
|
||||||
|
@ -81,7 +84,7 @@ empty = @Dict []
|
||||||
withCapacity : Nat -> Dict k v
|
withCapacity : Nat -> Dict k v
|
||||||
withCapacity = \n -> @Dict (List.withCapacity n)
|
withCapacity = \n -> @Dict (List.withCapacity n)
|
||||||
|
|
||||||
get : Dict k v, k -> Result v [KeyNotFound]*
|
get : Dict k v, k -> Result v [KeyNotFound]* | k has Eq
|
||||||
get = \@Dict list, needle ->
|
get = \@Dict list, needle ->
|
||||||
when List.findFirst list (\Pair key _ -> key == needle) is
|
when List.findFirst list (\Pair key _ -> key == needle) is
|
||||||
Ok (Pair _ v) ->
|
Ok (Pair _ v) ->
|
||||||
|
@ -94,7 +97,7 @@ walk : Dict k v, state, (state, k, v -> state) -> state
|
||||||
walk = \@Dict list, initialState, transform ->
|
walk = \@Dict list, initialState, transform ->
|
||||||
List.walk list initialState (\state, Pair k v -> transform state k v)
|
List.walk list initialState (\state, Pair k v -> transform state k v)
|
||||||
|
|
||||||
insert : Dict k v, k, v -> Dict k v
|
insert : Dict k v, k, v -> Dict k v | k has Eq
|
||||||
insert = \@Dict list, k, v ->
|
insert = \@Dict list, k, v ->
|
||||||
when List.findFirstIndex list (\Pair key _ -> key == k) is
|
when List.findFirstIndex list (\Pair key _ -> key == k) is
|
||||||
Err NotFound ->
|
Err NotFound ->
|
||||||
|
@ -109,7 +112,7 @@ len : Dict k v -> Nat
|
||||||
len = \@Dict list ->
|
len = \@Dict list ->
|
||||||
List.len list
|
List.len list
|
||||||
|
|
||||||
remove : Dict k v, k -> Dict k v
|
remove : Dict k v, k -> Dict k v | k has Eq
|
||||||
remove = \@Dict list, key ->
|
remove = \@Dict list, key ->
|
||||||
when List.findFirstIndex list (\Pair k _ -> k == key) is
|
when List.findFirstIndex list (\Pair k _ -> k == key) is
|
||||||
Err NotFound ->
|
Err NotFound ->
|
||||||
|
@ -128,7 +131,7 @@ update :
|
||||||
Dict k v,
|
Dict k v,
|
||||||
k,
|
k,
|
||||||
([Present v, Missing] -> [Present v, Missing])
|
([Present v, Missing] -> [Present v, Missing])
|
||||||
-> Dict k v
|
-> Dict k v | k has Eq
|
||||||
update = \dict, key, alter ->
|
update = \dict, key, alter ->
|
||||||
possibleValue =
|
possibleValue =
|
||||||
get dict key
|
get dict key
|
||||||
|
@ -151,7 +154,7 @@ expect update empty "a" alterValue == single "a" Bool.false
|
||||||
expect update (single "a" Bool.false) "a" alterValue == single "a" Bool.true
|
expect update (single "a" Bool.false) "a" alterValue == single "a" Bool.true
|
||||||
expect update (single "a" Bool.true) "a" alterValue == empty
|
expect update (single "a" Bool.true) "a" alterValue == empty
|
||||||
|
|
||||||
contains : Dict k v, k -> Bool
|
contains : Dict k v, k -> Bool | k has Eq
|
||||||
contains = \@Dict list, needle ->
|
contains = \@Dict list, needle ->
|
||||||
step = \_, Pair key _val ->
|
step = \_, Pair key _val ->
|
||||||
if key == needle then
|
if key == needle then
|
||||||
|
@ -178,18 +181,18 @@ values = \@Dict list ->
|
||||||
List.map list (\Pair _ v -> v)
|
List.map list (\Pair _ v -> v)
|
||||||
|
|
||||||
# union : Dict k v, Dict k v -> Dict k v
|
# union : Dict k v, Dict k v -> Dict k v
|
||||||
insertAll : Dict k v, Dict k v -> Dict k v
|
insertAll : Dict k v, Dict k v -> Dict k v | k has Eq
|
||||||
insertAll = \xs, @Dict ys ->
|
insertAll = \xs, @Dict ys ->
|
||||||
List.walk ys xs (\state, Pair k v -> Dict.insertIfVacant state k v)
|
List.walk ys xs (\state, Pair k v -> Dict.insertIfVacant state k v)
|
||||||
|
|
||||||
# intersection : Dict k v, Dict k v -> Dict k v
|
# intersection : Dict k v, Dict k v -> Dict k v
|
||||||
keepShared : Dict k v, Dict k v -> Dict k v
|
keepShared : Dict k v, Dict k v -> Dict k v | k has Eq
|
||||||
keepShared = \@Dict xs, ys ->
|
keepShared = \@Dict xs, ys ->
|
||||||
List.keepIf xs (\Pair k _ -> Dict.contains ys k)
|
List.keepIf xs (\Pair k _ -> Dict.contains ys k)
|
||||||
|> @Dict
|
|> @Dict
|
||||||
|
|
||||||
# difference : Dict k v, Dict k v -> Dict k v
|
# difference : Dict k v, Dict k v -> Dict k v
|
||||||
removeAll : Dict k v, Dict k v -> Dict k v
|
removeAll : Dict k v, Dict k v -> Dict k v | k has Eq
|
||||||
removeAll = \xs, @Dict ys ->
|
removeAll = \xs, @Dict ys ->
|
||||||
List.walk ys xs (\state, Pair k _ -> Dict.remove state k)
|
List.walk ys xs (\state, Pair k _ -> Dict.remove state k)
|
||||||
|
|
||||||
|
@ -202,7 +205,7 @@ insertFresh = \@Dict list, k, v ->
|
||||||
|> List.append (Pair k v)
|
|> List.append (Pair k v)
|
||||||
|> @Dict
|
|> @Dict
|
||||||
|
|
||||||
insertIfVacant : Dict k v, k, v -> Dict k v
|
insertIfVacant : Dict k v, k, v -> Dict k v | k has Eq
|
||||||
insertIfVacant = \dict, key, value ->
|
insertIfVacant = \dict, key, value ->
|
||||||
if Dict.contains dict key then
|
if Dict.contains dict key then
|
||||||
dict
|
dict
|
||||||
|
|
|
@ -6,7 +6,7 @@ interface Eq
|
||||||
structuralEq,
|
structuralEq,
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool,
|
Bool.{ Bool },
|
||||||
]
|
]
|
||||||
|
|
||||||
## A type that can be compared for total equality.
|
## A type that can be compared for total equality.
|
||||||
|
|
|
@ -34,6 +34,7 @@ interface Json
|
||||||
Dec,
|
Dec,
|
||||||
},
|
},
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Eq.{ Eq },
|
||||||
Result,
|
Result,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ interface List
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Eq.{ Eq },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
Num.{ Nat, Num, Int },
|
Num.{ Nat, Num, Int },
|
||||||
]
|
]
|
||||||
|
@ -354,7 +355,7 @@ join = \lists ->
|
||||||
|
|
||||||
List.walk lists (List.withCapacity totalLength) (\state, list -> List.concat state list)
|
List.walk lists (List.withCapacity totalLength) (\state, list -> List.concat state list)
|
||||||
|
|
||||||
contains : List a, a -> Bool
|
contains : List a, a -> Bool | a has Eq
|
||||||
contains = \list, needle ->
|
contains = \list, needle ->
|
||||||
List.any list (\x -> x == needle)
|
List.any list (\x -> x == needle)
|
||||||
|
|
||||||
|
@ -903,7 +904,7 @@ intersperse = \list, sep ->
|
||||||
## is considered to "start with" an empty list.
|
## 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.
|
## If the first list is empty, this only returns `Bool.true` if the second list is empty.
|
||||||
startsWith : List elem, List elem -> Bool
|
startsWith : List elem, List elem -> Bool | elem has Eq
|
||||||
startsWith = \list, prefix ->
|
startsWith = \list, prefix ->
|
||||||
# TODO once we have seamless slices, verify that this wouldn't
|
# TODO once we have seamless slices, verify that this wouldn't
|
||||||
# have better performance with a function like List.compareSublists
|
# have better performance with a function like List.compareSublists
|
||||||
|
@ -915,7 +916,7 @@ startsWith = \list, prefix ->
|
||||||
## is considered to "end with" an empty list.
|
## 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.
|
## If the first list is empty, this only returns `Bool.true` if the second list is empty.
|
||||||
endsWith : List elem, List elem -> Bool
|
endsWith : List elem, List elem -> Bool | elem has Eq
|
||||||
endsWith = \list, suffix ->
|
endsWith = \list, suffix ->
|
||||||
# TODO once we have seamless slices, verify that this wouldn't
|
# TODO once we have seamless slices, verify that this wouldn't
|
||||||
# have better performance with a function like List.compareSublists
|
# have better performance with a function like List.compareSublists
|
||||||
|
@ -944,7 +945,7 @@ split = \elements, userSplitIndex ->
|
||||||
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
||||||
##
|
##
|
||||||
## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Baz] }
|
## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Baz] }
|
||||||
splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]*
|
splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]* | elem has Eq
|
||||||
splitFirst = \list, delimiter ->
|
splitFirst = \list, delimiter ->
|
||||||
when List.findFirstIndex list (\elem -> elem == delimiter) is
|
when List.findFirstIndex list (\elem -> elem == delimiter) is
|
||||||
Ok index ->
|
Ok index ->
|
||||||
|
@ -959,7 +960,7 @@ splitFirst = \list, delimiter ->
|
||||||
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
||||||
##
|
##
|
||||||
## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Bar], after: [Baz] }
|
## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Bar], after: [Baz] }
|
||||||
splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]*
|
splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]* | elem has Eq
|
||||||
splitLast = \list, delimiter ->
|
splitLast = \list, delimiter ->
|
||||||
when List.findLastIndex list (\elem -> elem == delimiter) is
|
when List.findLastIndex list (\elem -> elem == delimiter) is
|
||||||
Ok index ->
|
Ok index ->
|
||||||
|
|
|
@ -146,6 +146,7 @@ interface Num
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
|
Eq,
|
||||||
]
|
]
|
||||||
|
|
||||||
## Represents a number that could be either an [Int] or a [Frac].
|
## Represents a number that could be either an [Int] or a [Frac].
|
||||||
|
@ -793,7 +794,7 @@ div : Frac a, Frac a -> Frac a
|
||||||
|
|
||||||
divChecked : Frac a, Frac a -> Result (Frac a) [DivByZero]*
|
divChecked : Frac a, Frac a -> Result (Frac a) [DivByZero]*
|
||||||
divChecked = \a, b ->
|
divChecked = \a, b ->
|
||||||
if b == 0 then
|
if Num.isZero b then
|
||||||
Err DivByZero
|
Err DivByZero
|
||||||
else
|
else
|
||||||
Ok (Num.div a b)
|
Ok (Num.div a b)
|
||||||
|
@ -802,7 +803,7 @@ divCeil : Int a, Int a -> Int a
|
||||||
|
|
||||||
divCeilChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
divCeilChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
||||||
divCeilChecked = \a, b ->
|
divCeilChecked = \a, b ->
|
||||||
if b == 0 then
|
if Num.isZero b then
|
||||||
Err DivByZero
|
Err DivByZero
|
||||||
else
|
else
|
||||||
Ok (Num.divCeil a b)
|
Ok (Num.divCeil a b)
|
||||||
|
@ -827,7 +828,7 @@ divTrunc : Int a, Int a -> Int a
|
||||||
|
|
||||||
divTruncChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
divTruncChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
||||||
divTruncChecked = \a, b ->
|
divTruncChecked = \a, b ->
|
||||||
if b == 0 then
|
if Num.isZero b then
|
||||||
Err DivByZero
|
Err DivByZero
|
||||||
else
|
else
|
||||||
Ok (Num.divTrunc a b)
|
Ok (Num.divTrunc a b)
|
||||||
|
@ -847,7 +848,7 @@ rem : Int a, Int a -> Int a
|
||||||
|
|
||||||
remChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
remChecked : Int a, Int a -> Result (Int a) [DivByZero]*
|
||||||
remChecked = \a, b ->
|
remChecked = \a, b ->
|
||||||
if b == 0 then
|
if Num.isZero b then
|
||||||
Err DivByZero
|
Err DivByZero
|
||||||
else
|
else
|
||||||
Ok (Num.rem a b)
|
Ok (Num.rem a b)
|
||||||
|
|
|
@ -14,9 +14,11 @@ interface Set
|
||||||
intersection,
|
intersection,
|
||||||
difference,
|
difference,
|
||||||
]
|
]
|
||||||
imports [List, Bool.{ Bool }, Dict.{ Dict }, Num.{ Nat }]
|
imports [List, Bool.{ Bool }, Eq.{ Eq }, Dict.{ Dict }, Num.{ Nat }]
|
||||||
|
|
||||||
Set k := Dict.Dict k {}
|
Set k := Dict.Dict k {} has [Eq { isEq: setEq }]
|
||||||
|
|
||||||
|
setEq = \@Set d1, @Set d2 -> d1 == d2
|
||||||
|
|
||||||
fromDict : Dict k {} -> Set k
|
fromDict : Dict k {} -> Set k
|
||||||
fromDict = \dict -> @Set dict
|
fromDict = \dict -> @Set dict
|
||||||
|
@ -35,7 +37,7 @@ single = \key ->
|
||||||
## Make sure never to insert a *NaN* to a [Set]! Because *NaN* is defined to be
|
## Make sure never to insert a *NaN* to a [Set]! Because *NaN* is defined to be
|
||||||
## unequal to *NaN*, adding a *NaN* results in an entry that can never be
|
## unequal to *NaN*, adding a *NaN* results in an entry that can never be
|
||||||
## retrieved or removed from the [Set].
|
## retrieved or removed from the [Set].
|
||||||
insert : Set k, k -> Set k
|
insert : Set k, k -> Set k | k has Eq
|
||||||
insert = \@Set dict, key ->
|
insert = \@Set dict, key ->
|
||||||
dict
|
dict
|
||||||
|> Dict.insert key {}
|
|> Dict.insert key {}
|
||||||
|
@ -75,11 +77,11 @@ expect
|
||||||
actual == 3
|
actual == 3
|
||||||
|
|
||||||
## Drops the given element from the set.
|
## Drops the given element from the set.
|
||||||
remove : Set k, k -> Set k
|
remove : Set k, k -> Set k | k has Eq
|
||||||
remove = \@Set dict, key ->
|
remove = \@Set dict, key ->
|
||||||
@Set (Dict.remove dict key)
|
@Set (Dict.remove dict key)
|
||||||
|
|
||||||
contains : Set k, k -> Bool
|
contains : Set k, k -> Bool | k has Eq
|
||||||
contains = \set, key ->
|
contains = \set, key ->
|
||||||
set
|
set
|
||||||
|> Set.toDict
|
|> Set.toDict
|
||||||
|
@ -89,21 +91,21 @@ toList : Set k -> List k
|
||||||
toList = \@Set dict ->
|
toList = \@Set dict ->
|
||||||
Dict.keys dict
|
Dict.keys dict
|
||||||
|
|
||||||
fromList : List k -> Set k
|
fromList : List k -> Set k | k has Eq
|
||||||
fromList = \list ->
|
fromList = \list ->
|
||||||
initial = @Set (Dict.withCapacity (List.len list))
|
initial = @Set (Dict.withCapacity (List.len list))
|
||||||
|
|
||||||
List.walk list initial \set, key -> Set.insert set key
|
List.walk list initial \set, key -> Set.insert set key
|
||||||
|
|
||||||
union : Set k, Set k -> Set k
|
union : Set k, Set k -> Set k | k has Eq
|
||||||
union = \@Set dict1, @Set dict2 ->
|
union = \@Set dict1, @Set dict2 ->
|
||||||
@Set (Dict.insertAll dict1 dict2)
|
@Set (Dict.insertAll dict1 dict2)
|
||||||
|
|
||||||
intersection : Set k, Set k -> Set k
|
intersection : Set k, Set k -> Set k | k has Eq
|
||||||
intersection = \@Set dict1, @Set dict2 ->
|
intersection = \@Set dict1, @Set dict2 ->
|
||||||
@Set (Dict.keepShared dict1 dict2)
|
@Set (Dict.keepShared dict1 dict2)
|
||||||
|
|
||||||
difference : Set k, Set k -> Set k
|
difference : Set k, Set k -> Set k | k has Eq
|
||||||
difference = \@Set dict1, @Set dict2 ->
|
difference = \@Set dict1, @Set dict2 ->
|
||||||
@Set (Dict.removeAll dict1 dict2)
|
@Set (Dict.removeAll dict1 dict2)
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ interface Str
|
||||||
]
|
]
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool },
|
Bool.{ Bool },
|
||||||
|
Eq.{ Eq },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
List,
|
List,
|
||||||
Num.{ Nat, Num, U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec },
|
Num.{ Nat, Num, U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec },
|
||||||
|
|
|
@ -409,7 +409,7 @@ fn binop_to_function(binop: BinOp) -> (&'static str, &'static str) {
|
||||||
Percent => (ModuleName::NUM, "rem"),
|
Percent => (ModuleName::NUM, "rem"),
|
||||||
Plus => (ModuleName::NUM, "add"),
|
Plus => (ModuleName::NUM, "add"),
|
||||||
Minus => (ModuleName::NUM, "sub"),
|
Minus => (ModuleName::NUM, "sub"),
|
||||||
Equals => (ModuleName::BOOL, "isEq"),
|
Equals => (ModuleName::EQ, "isEq"),
|
||||||
NotEquals => (ModuleName::BOOL, "isNotEq"),
|
NotEquals => (ModuleName::BOOL, "isNotEq"),
|
||||||
LessThan => (ModuleName::NUM, "isLt"),
|
LessThan => (ModuleName::NUM, "isLt"),
|
||||||
GreaterThan => (ModuleName::NUM, "isGt"),
|
GreaterThan => (ModuleName::NUM, "isGt"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue