mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Warn on the presence of unnecessary wildcards in output positions
This commit is contained in:
parent
d55dbbf0ae
commit
cfe7c8e5ef
17 changed files with 151 additions and 106 deletions
|
@ -991,7 +991,7 @@ mod cli_run {
|
|||
|
||||
This #UserApp.main value is a:
|
||||
|
||||
Task.Task {} * [Write [Stdout]*]* ?
|
||||
Task.Task {} * [Write [Stdout]a]b ?
|
||||
|
||||
But the type annotation on main says it should be:
|
||||
|
||||
|
@ -1012,7 +1012,7 @@ mod cli_run {
|
|||
|
||||
This #UserApp.main value is a:
|
||||
|
||||
Task.Task {} * [Write [Stdout]*]* ?
|
||||
Task.Task {} * [Write [Stdout]a]b ?
|
||||
|
||||
But toEffect needs its 1st argument to be:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
interface Base64 exposes [fromBytes, fromStr, toBytes, toStr] imports [Base64.Decode, Base64.Encode]
|
||||
|
||||
# base 64 encoding from a sequence of bytes
|
||||
fromBytes : List U8 -> Result Str [InvalidInput]*
|
||||
fromBytes : List U8 -> Result Str [InvalidInput]
|
||||
fromBytes = \bytes ->
|
||||
when Base64.Decode.fromBytes bytes is
|
||||
Ok v ->
|
||||
|
@ -11,16 +11,16 @@ fromBytes = \bytes ->
|
|||
Err InvalidInput
|
||||
|
||||
# base 64 encoding from a string
|
||||
fromStr : Str -> Result Str [InvalidInput]*
|
||||
fromStr : Str -> Result Str [InvalidInput]
|
||||
fromStr = \str ->
|
||||
fromBytes (Str.toUtf8 str)
|
||||
|
||||
# base64-encode bytes to the original
|
||||
toBytes : Str -> Result (List U8) [InvalidInput]*
|
||||
toBytes : Str -> Result (List U8) [InvalidInput]
|
||||
toBytes = \str ->
|
||||
Ok (Base64.Encode.toBytes str)
|
||||
|
||||
toStr : Str -> Result Str [InvalidInput]*
|
||||
toStr : Str -> Result Str [InvalidInput]
|
||||
toStr = \str ->
|
||||
when toBytes str is
|
||||
Ok bytes ->
|
||||
|
|
|
@ -36,7 +36,7 @@ nestHelp = \{ s, f, m, x } ->
|
|||
|
||||
Expr : [Val I64, Var Str, Add Expr Expr, Mul Expr Expr, Pow Expr Expr, Ln Expr]
|
||||
|
||||
divmod : I64, I64 -> Result { div : I64, mod : I64 } [DivByZero]*
|
||||
divmod : I64, I64 -> Result { div : I64, mod : I64 } [DivByZero]
|
||||
divmod = \l, r ->
|
||||
when Pair (Num.divTruncChecked l r) (Num.remChecked l r) is
|
||||
Pair (Ok div) (Ok mod) -> Ok { div, mod }
|
||||
|
|
|
@ -105,7 +105,7 @@ withCapacity = \n -> @Dict (List.withCapacity n)
|
|||
##
|
||||
## expect Dict.get dictionary 1 == Ok "Apple"
|
||||
## expect Dict.get dictionary 2000 == Err KeyNotFound
|
||||
get : Dict k v, k -> Result v [KeyNotFound]* | k has Eq
|
||||
get : Dict k v, k -> Result v [KeyNotFound] | k has Eq
|
||||
get = \@Dict list, needle ->
|
||||
when List.findFirst list (\Pair key _ -> key == needle) is
|
||||
Ok (Pair _ v) ->
|
||||
|
|
|
@ -219,7 +219,7 @@ isEmpty = \list ->
|
|||
# but will cause a reference count increment on the value it got out of the list
|
||||
getUnsafe : List a, Nat -> a
|
||||
|
||||
get : List a, Nat -> Result a [OutOfBounds]*
|
||||
get : List a, Nat -> Result a [OutOfBounds]
|
||||
get = \list, index ->
|
||||
if index < List.len list then
|
||||
Ok (List.getUnsafe list index)
|
||||
|
@ -298,7 +298,7 @@ reserve : List a, Nat -> List a
|
|||
concat : List a, List a -> List a
|
||||
|
||||
## Returns the last element in the list, or `ListWasEmpty` if it was empty.
|
||||
last : List a -> Result a [ListWasEmpty]*
|
||||
last : List a -> Result a [ListWasEmpty]
|
||||
last = \list ->
|
||||
when List.get list (Num.subSaturated (List.len list) 1) is
|
||||
Ok v -> Ok v
|
||||
|
@ -683,7 +683,7 @@ sortDesc = \list -> List.sortWith list (\a, b -> Num.compare b a)
|
|||
swap : List a, Nat, Nat -> List a
|
||||
|
||||
## Returns the first element in the list, or `ListWasEmpty` if it was empty.
|
||||
first : List a -> Result a [ListWasEmpty]*
|
||||
first : List a -> Result a [ListWasEmpty]
|
||||
first = \list ->
|
||||
when List.get list 0 is
|
||||
Ok v -> Ok v
|
||||
|
@ -776,7 +776,7 @@ drop = \list, n ->
|
|||
## To replace the element at a given index, instead of dropping it, see [List.set].
|
||||
dropAt : List elem, Nat -> List elem
|
||||
|
||||
min : List (Num a) -> Result (Num a) [ListWasEmpty]*
|
||||
min : List (Num a) -> Result (Num a) [ListWasEmpty]
|
||||
min = \list ->
|
||||
when List.first list is
|
||||
Ok initial ->
|
||||
|
@ -793,7 +793,7 @@ minHelp = \list, initial ->
|
|||
else
|
||||
bestSoFar
|
||||
|
||||
max : List (Num a) -> Result (Num a) [ListWasEmpty]*
|
||||
max : List (Num a) -> Result (Num a) [ListWasEmpty]
|
||||
max = \list ->
|
||||
when List.first list is
|
||||
Ok initial ->
|
||||
|
@ -820,7 +820,7 @@ joinMap = \list, mapper ->
|
|||
|
||||
## Returns the first element of the list satisfying a predicate function.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findFirst : List elem, (elem -> Bool) -> Result elem [NotFound]*
|
||||
findFirst : List elem, (elem -> Bool) -> Result elem [NotFound]
|
||||
findFirst = \list, pred ->
|
||||
callback = \_, elem ->
|
||||
if pred elem then
|
||||
|
@ -834,7 +834,7 @@ findFirst = \list, pred ->
|
|||
|
||||
## Returns the last element of the list satisfying a predicate function.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findLast : List elem, (elem -> Bool) -> Result elem [NotFound]*
|
||||
findLast : List elem, (elem -> Bool) -> Result elem [NotFound]
|
||||
findLast = \list, pred ->
|
||||
callback = \_, elem ->
|
||||
if pred elem then
|
||||
|
@ -849,7 +849,7 @@ findLast = \list, pred ->
|
|||
## Returns the index at which the first element in the list
|
||||
## satisfying a predicate function can be found.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findFirstIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
|
||||
findFirstIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]
|
||||
findFirstIndex = \list, matcher ->
|
||||
foundIndex = List.iterate list 0 \index, elem ->
|
||||
if matcher elem then
|
||||
|
@ -864,7 +864,7 @@ findFirstIndex = \list, matcher ->
|
|||
## Returns the last index at which the first element in the list
|
||||
## satisfying a predicate function can be found.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findLastIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
|
||||
findLastIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]
|
||||
findLastIndex = \list, matches ->
|
||||
foundIndex = List.iterateBackwards list (List.len list) \prevIndex, elem ->
|
||||
if matches elem then
|
||||
|
@ -962,7 +962,7 @@ split = \elements, userSplitIndex ->
|
|||
## 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] }
|
||||
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 has Eq
|
||||
splitFirst = \list, delimiter ->
|
||||
when List.findFirstIndex list (\elem -> elem == delimiter) is
|
||||
Ok index ->
|
||||
|
@ -977,7 +977,7 @@ splitFirst = \list, delimiter ->
|
|||
## 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] }
|
||||
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 has Eq
|
||||
splitLast = \list, delimiter ->
|
||||
when List.findLastIndex list (\elem -> elem == delimiter) is
|
||||
Ok index ->
|
||||
|
|
|
@ -743,7 +743,7 @@ atan : Frac a -> Frac a
|
|||
## >>> Num.sqrt -4.0f64
|
||||
sqrt : Frac a -> Frac a
|
||||
|
||||
sqrtChecked : Frac a -> Result (Frac a) [SqrtOfNegative]*
|
||||
sqrtChecked : Frac a -> Result (Frac a) [SqrtOfNegative]
|
||||
sqrtChecked = \x ->
|
||||
if x < 0.0 then
|
||||
Err SqrtOfNegative
|
||||
|
@ -752,7 +752,7 @@ sqrtChecked = \x ->
|
|||
|
||||
log : Frac a -> Frac a
|
||||
|
||||
logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]*
|
||||
logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]
|
||||
logChecked = \x ->
|
||||
if x <= 0.0 then
|
||||
Err LogNeedsPositive
|
||||
|
@ -791,7 +791,7 @@ logChecked = \x ->
|
|||
## >>> |> Num.div 2.0
|
||||
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 ->
|
||||
if Num.isZero b then
|
||||
Err DivByZero
|
||||
|
@ -800,7 +800,7 @@ divChecked = \a, b ->
|
|||
|
||||
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 ->
|
||||
if Num.isZero b then
|
||||
Err DivByZero
|
||||
|
@ -825,7 +825,7 @@ divCeilChecked = \a, b ->
|
|||
##
|
||||
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 ->
|
||||
if Num.isZero b then
|
||||
Err DivByZero
|
||||
|
@ -845,7 +845,7 @@ divTruncChecked = \a, b ->
|
|||
## >>> Num.rem -8 -3
|
||||
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 ->
|
||||
if Num.isZero b then
|
||||
Err DivByZero
|
||||
|
@ -944,7 +944,7 @@ addSaturated : Num a, Num a -> Num a
|
|||
##
|
||||
## This is the same as [Num.add] except if the operation overflows, instead of
|
||||
## panicking or returning ∞ or -∞, it will return `Err Overflow`.
|
||||
addChecked : Num a, Num a -> Result (Num a) [Overflow]*
|
||||
addChecked : Num a, Num a -> Result (Num a) [Overflow]
|
||||
addChecked = \a, b ->
|
||||
result = addCheckedLowlevel a b
|
||||
|
||||
|
@ -970,7 +970,7 @@ subSaturated : Num a, Num a -> Num a
|
|||
##
|
||||
## This is the same as [Num.sub] except if the operation overflows, instead of
|
||||
## panicking or returning ∞ or -∞, it will return `Err Overflow`.
|
||||
subChecked : Num a, Num a -> Result (Num a) [Overflow]*
|
||||
subChecked : Num a, Num a -> Result (Num a) [Overflow]
|
||||
subChecked = \a, b ->
|
||||
result = subCheckedLowlevel a b
|
||||
|
||||
|
@ -994,7 +994,7 @@ mulSaturated : Num a, Num a -> Num a
|
|||
##
|
||||
## This is the same as [Num.mul] except if the operation overflows, instead of
|
||||
## panicking or returning ∞ or -∞, it will return `Err Overflow`.
|
||||
mulChecked : Num a, Num a -> Result (Num a) [Overflow]*
|
||||
mulChecked : Num a, Num a -> Result (Num a) [Overflow]
|
||||
mulChecked = \a, b ->
|
||||
result = mulCheckedLowlevel a b
|
||||
|
||||
|
@ -1250,19 +1250,19 @@ toF64 : Num * -> F64
|
|||
## Converts a [Int] to an [I8].
|
||||
## If the given integer can't be precisely represented in an [I8], returns
|
||||
## `Err OutOfBounds`.
|
||||
toI8Checked : Int * -> Result I8 [OutOfBounds]*
|
||||
toI16Checked : Int * -> Result I16 [OutOfBounds]*
|
||||
toI32Checked : Int * -> Result I32 [OutOfBounds]*
|
||||
toI64Checked : Int * -> Result I64 [OutOfBounds]*
|
||||
toI128Checked : Int * -> Result I128 [OutOfBounds]*
|
||||
toU8Checked : Int * -> Result U8 [OutOfBounds]*
|
||||
toU16Checked : Int * -> Result U16 [OutOfBounds]*
|
||||
toU32Checked : Int * -> Result U32 [OutOfBounds]*
|
||||
toU64Checked : Int * -> Result U64 [OutOfBounds]*
|
||||
toU128Checked : Int * -> Result U128 [OutOfBounds]*
|
||||
toNatChecked : Int * -> Result Nat [OutOfBounds]*
|
||||
toF32Checked : Num * -> Result F32 [OutOfBounds]*
|
||||
toF64Checked : Num * -> Result F64 [OutOfBounds]*
|
||||
toI8Checked : Int * -> Result I8 [OutOfBounds]
|
||||
toI16Checked : Int * -> Result I16 [OutOfBounds]
|
||||
toI32Checked : Int * -> Result I32 [OutOfBounds]
|
||||
toI64Checked : Int * -> Result I64 [OutOfBounds]
|
||||
toI128Checked : Int * -> Result I128 [OutOfBounds]
|
||||
toU8Checked : Int * -> Result U8 [OutOfBounds]
|
||||
toU16Checked : Int * -> Result U16 [OutOfBounds]
|
||||
toU32Checked : Int * -> Result U32 [OutOfBounds]
|
||||
toU64Checked : Int * -> Result U64 [OutOfBounds]
|
||||
toU128Checked : Int * -> Result U128 [OutOfBounds]
|
||||
toNatChecked : Int * -> Result Nat [OutOfBounds]
|
||||
toF32Checked : Num * -> Result F32 [OutOfBounds]
|
||||
toF64Checked : Num * -> Result F64 [OutOfBounds]
|
||||
|
||||
# Special Floating-Point operations
|
||||
## When given a [F64] or [F32] value, returns `Bool.false` if that value is
|
||||
|
|
|
@ -220,7 +220,7 @@ toUtf8 : Str -> List U8
|
|||
##
|
||||
## expect Str.fromUtf8 [233, 185, 143] == Ok "鹏"
|
||||
## expect Str.fromUtf8 [0xb0] == Err (BadUtf8 InvalidStartByte 0)
|
||||
fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]*
|
||||
fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]
|
||||
fromUtf8 = \bytes ->
|
||||
result = fromUtf8RangeLowlevel bytes 0 (List.len bytes)
|
||||
|
||||
|
@ -233,7 +233,7 @@ fromUtf8 = \bytes ->
|
|||
## into a [Str]
|
||||
##
|
||||
## expect Str.fromUtf8Range [72, 105, 80, 103] { start : 0, count : 2 } == Ok "Hi"
|
||||
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds]*
|
||||
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds]
|
||||
fromUtf8Range = \bytes, config ->
|
||||
if config.start + config.count <= List.len bytes then
|
||||
result = fromUtf8RangeLowlevel bytes config.start config.count
|
||||
|
@ -288,7 +288,7 @@ trimRight : Str -> Str
|
|||
## expect Str.toDec "10" == Ok 10dec
|
||||
## expect Str.toDec "-0.25" == Ok -0.25dec
|
||||
## expect Str.toDec "not a number" == Err InvalidNumStr
|
||||
toDec : Str -> Result Dec [InvalidNumStr]*
|
||||
toDec : Str -> Result Dec [InvalidNumStr]
|
||||
toDec = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a [F64]. A [F64] value is a 64-bit
|
||||
|
@ -297,7 +297,7 @@ toDec = \string -> strToNumHelp string
|
|||
##
|
||||
## expect Str.toF64 "0.10" == Ok 0.10f64
|
||||
## expect Str.toF64 "not a number" == Err InvalidNumStr
|
||||
toF64 : Str -> Result F64 [InvalidNumStr]*
|
||||
toF64 : Str -> Result F64 [InvalidNumStr]
|
||||
toF64 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a [F32].A [F32] value is a 32-bit
|
||||
|
@ -306,7 +306,7 @@ toF64 = \string -> strToNumHelp string
|
|||
##
|
||||
## expect Str.toF32 "0.10" == Ok 0.10f32
|
||||
## expect Str.toF32 "not a number" == Err InvalidNumStr
|
||||
toF32 : Str -> Result F32 [InvalidNumStr]*
|
||||
toF32 : Str -> Result F32 [InvalidNumStr]
|
||||
toF32 = \string -> strToNumHelp string
|
||||
|
||||
## Convert a [Str] to a [Nat]. If the given number doesn't fit in [Nat], it will be [truncated](https://www.ualberta.ca/computing-science/media-library/teaching-resources/java/truncation-rounding.html).
|
||||
|
@ -324,7 +324,7 @@ toF32 = \string -> strToNumHelp string
|
|||
##
|
||||
## expect Str.toNat "9_000_000_000" == Ok 9000000000
|
||||
## expect Str.toNat "not a number" == Err InvalidNumStr
|
||||
toNat : Str -> Result Nat [InvalidNumStr]*
|
||||
toNat : Str -> Result Nat [InvalidNumStr]
|
||||
toNat = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to an unsigned [U128] integer. A [U128] value can hold numbers
|
||||
|
@ -335,7 +335,7 @@ toNat = \string -> strToNumHelp string
|
|||
## expect Str.toU128 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toU128 "-1" == Err InvalidNumStr
|
||||
## expect Str.toU128 "not a number" == Err InvalidNumStr
|
||||
toU128 : Str -> Result U128 [InvalidNumStr]*
|
||||
toU128 : Str -> Result U128 [InvalidNumStr]
|
||||
toU128 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a signed [I128] integer. A [I128] value can hold numbers
|
||||
|
@ -347,7 +347,7 @@ toU128 = \string -> strToNumHelp string
|
|||
## expect Str.toI128 "-1" == Ok -1i128
|
||||
## expect Str.toI128 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toI128 "not a number" == Err InvalidNumStr
|
||||
toI128 : Str -> Result I128 [InvalidNumStr]*
|
||||
toI128 : Str -> Result I128 [InvalidNumStr]
|
||||
toI128 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to an unsigned [U64] integer. A [U64] value can hold numbers
|
||||
|
@ -358,7 +358,7 @@ toI128 = \string -> strToNumHelp string
|
|||
## expect Str.toU64 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toU64 "-1" == Err InvalidNumStr
|
||||
## expect Str.toU64 "not a number" == Err InvalidNumStr
|
||||
toU64 : Str -> Result U64 [InvalidNumStr]*
|
||||
toU64 : Str -> Result U64 [InvalidNumStr]
|
||||
toU64 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a signed [I64] integer. A [I64] value can hold numbers
|
||||
|
@ -369,7 +369,7 @@ toU64 = \string -> strToNumHelp string
|
|||
## expect Str.toI64 "-1" == Ok -1i64
|
||||
## expect Str.toI64 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toI64 "not a number" == Err InvalidNumStr
|
||||
toI64 : Str -> Result I64 [InvalidNumStr]*
|
||||
toI64 : Str -> Result I64 [InvalidNumStr]
|
||||
toI64 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to an unsigned [U32] integer. A [U32] value can hold numbers
|
||||
|
@ -380,7 +380,7 @@ toI64 = \string -> strToNumHelp string
|
|||
## expect Str.toU32 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toU32 "-1" == Err InvalidNumStr
|
||||
## expect Str.toU32 "not a number" == Err InvalidNumStr
|
||||
toU32 : Str -> Result U32 [InvalidNumStr]*
|
||||
toU32 : Str -> Result U32 [InvalidNumStr]
|
||||
toU32 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a signed [I32] integer. A [I32] value can hold numbers
|
||||
|
@ -391,7 +391,7 @@ toU32 = \string -> strToNumHelp string
|
|||
## expect Str.toI32 "-1" == Ok -1i32
|
||||
## expect Str.toI32 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toI32 "not a number" == Err InvalidNumStr
|
||||
toI32 : Str -> Result I32 [InvalidNumStr]*
|
||||
toI32 : Str -> Result I32 [InvalidNumStr]
|
||||
toI32 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to an unsigned [U16] integer. A [U16] value can hold numbers
|
||||
|
@ -401,7 +401,7 @@ toI32 = \string -> strToNumHelp string
|
|||
## expect Str.toU16 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toU16 "-1" == Err InvalidNumStr
|
||||
## expect Str.toU16 "not a number" == Err InvalidNumStr
|
||||
toU16 : Str -> Result U16 [InvalidNumStr]*
|
||||
toU16 : Str -> Result U16 [InvalidNumStr]
|
||||
toU16 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a signed [I16] integer. A [I16] value can hold numbers
|
||||
|
@ -412,7 +412,7 @@ toU16 = \string -> strToNumHelp string
|
|||
## expect Str.toI16 "-1" == Ok -1i16
|
||||
## expect Str.toI16 "0.1" == Err InvalidNumStr
|
||||
## expect Str.toI16 "not a number" == Err InvalidNumStr
|
||||
toI16 : Str -> Result I16 [InvalidNumStr]*
|
||||
toI16 : Str -> Result I16 [InvalidNumStr]
|
||||
toI16 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to an unsigned [U8] integer. A [U8] value can hold numbers
|
||||
|
@ -422,7 +422,7 @@ toI16 = \string -> strToNumHelp string
|
|||
## expect Str.toU8 "-0.1" == Err InvalidNumStr
|
||||
## expect Str.toU8 "not a number" == Err InvalidNumStr
|
||||
## expect Str.toU8 "1500" == Err InvalidNumStr
|
||||
toU8 : Str -> Result U8 [InvalidNumStr]*
|
||||
toU8 : Str -> Result U8 [InvalidNumStr]
|
||||
toU8 = \string -> strToNumHelp string
|
||||
|
||||
## Encode a [Str] to a signed [I8] integer. A [I8] value can hold numbers
|
||||
|
@ -432,7 +432,7 @@ toU8 = \string -> strToNumHelp string
|
|||
## expect Str.toI8 "-15" == Ok -15i8
|
||||
## expect Str.toI8 "150.00" == Err InvalidNumStr
|
||||
## expect Str.toI8 "not a number" == Err InvalidNumStr
|
||||
toI8 : Str -> Result I8 [InvalidNumStr]*
|
||||
toI8 : Str -> Result I8 [InvalidNumStr]
|
||||
toI8 = \string -> strToNumHelp string
|
||||
|
||||
## Get the byte at the given index, without performing a bounds check.
|
||||
|
@ -451,7 +451,7 @@ substringUnsafe : Str, Nat, Nat -> Str
|
|||
##
|
||||
## expect Str.replaceEach "foo/bar/baz" "/" "_" == Ok "foo_bar_baz"
|
||||
## expect Str.replaceEach "not here" "/" "_" == Err NotFound
|
||||
replaceEach : Str, Str, Str -> Result Str [NotFound]*
|
||||
replaceEach : Str, Str, Str -> Result Str [NotFound]
|
||||
replaceEach = \haystack, needle, flower ->
|
||||
when splitFirst haystack needle is
|
||||
Ok { before, after } ->
|
||||
|
@ -483,7 +483,7 @@ expect Str.replaceEach "abXdeXghi" "X" "_" == Ok "ab_de_ghi"
|
|||
##
|
||||
## expect Str.replaceFirst "foo/bar/baz" "/" "_" == Ok "foo_bar/baz"
|
||||
## expect Str.replaceFirst "no slashes here" "/" "_" == Err NotFound
|
||||
replaceFirst : Str, Str, Str -> Result Str [NotFound]*
|
||||
replaceFirst : Str, Str, Str -> Result Str [NotFound]
|
||||
replaceFirst = \haystack, needle, flower ->
|
||||
when splitFirst haystack needle is
|
||||
Ok { before, after } ->
|
||||
|
@ -498,7 +498,7 @@ expect Str.replaceFirst "abXdeXghi" "X" "_" == Ok "ab_deXghi"
|
|||
##
|
||||
## expect Str.replaceLast "foo/bar/baz" "/" "_" == Ok "foo/bar_baz"
|
||||
## expect Str.replaceLast "no slashes here" "/" "_" == Err NotFound
|
||||
replaceLast : Str, Str, Str -> Result Str [NotFound]*
|
||||
replaceLast : Str, Str, Str -> Result Str [NotFound]
|
||||
replaceLast = \haystack, needle, flower ->
|
||||
when splitLast haystack needle is
|
||||
Ok { before, after } ->
|
||||
|
@ -514,7 +514,7 @@ expect Str.replaceLast "abXdeXghi" "X" "_" == Ok "abXde_ghi"
|
|||
##
|
||||
## expect Str.splitFirst "foo/bar/baz" "/" == Ok { before: "foo", after: "bar/baz" }
|
||||
## expect Str.splitFirst "no slashes here" "/" == Err NotFound
|
||||
splitFirst : Str, Str -> Result { before : Str, after : Str } [NotFound]*
|
||||
splitFirst : Str, Str -> Result { before : Str, after : Str } [NotFound]
|
||||
splitFirst = \haystack, needle ->
|
||||
when firstMatch haystack needle is
|
||||
Some index ->
|
||||
|
@ -567,7 +567,7 @@ firstMatchHelp = \haystack, needle, index, lastPossible ->
|
|||
##
|
||||
## expect Str.splitLast "foo/bar/baz" "/" == Ok { before: "foo/bar", after: "baz" }
|
||||
## expect Str.splitLast "no slashes here" "/" == Err NotFound
|
||||
splitLast : Str, Str -> Result { before : Str, after : Str } [NotFound]*
|
||||
splitLast : Str, Str -> Result { before : Str, after : Str } [NotFound]
|
||||
splitLast = \haystack, needle ->
|
||||
when lastMatch haystack needle is
|
||||
Some index ->
|
||||
|
@ -684,7 +684,7 @@ appendScalarUnsafe : Str, U32 -> Str
|
|||
##
|
||||
## expect Str.appendScalar "H" 105 == Ok "Hi"
|
||||
## expect Str.appendScalar "😢" 0xabcdef == Err InvalidScalar
|
||||
appendScalar : Str, U32 -> Result Str [InvalidScalar]*
|
||||
appendScalar : Str, U32 -> Result Str [InvalidScalar]
|
||||
appendScalar = \string, scalar ->
|
||||
if isValidScalar scalar then
|
||||
Ok (appendScalarUnsafe string scalar)
|
||||
|
@ -749,7 +749,7 @@ walkScalarsUntilHelp = \string, state, step, index, length ->
|
|||
|
||||
strToNum : Str -> { berrorcode : U8, aresult : Num * }
|
||||
|
||||
strToNumHelp : Str -> Result (Num a) [InvalidNumStr]*
|
||||
strToNumHelp : Str -> Result (Num a) [InvalidNumStr]
|
||||
strToNumHelp = \string ->
|
||||
result : { berrorcode : U8, aresult : Num a }
|
||||
result = strToNum string
|
||||
|
|
|
@ -334,7 +334,7 @@ pub(crate) fn canonicalize_annotation(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum CanPolarity {
|
||||
/// Polarity should be disregarded for now; relevant in aliaes + opaques.
|
||||
Disregard,
|
||||
|
@ -1081,6 +1081,17 @@ fn can_extension_type<'a>(
|
|||
references,
|
||||
);
|
||||
if valid_extension_type(shallow_dealias_with_scope(scope, &ext_type)) {
|
||||
if matches!(loc_ann.extract_spaces().item, TypeAnnotation::Wildcard)
|
||||
&& matches!(ext_problem_kind, ExtensionTypeKind::TagUnion)
|
||||
&& pol == CanPolarity::Pos
|
||||
{
|
||||
// Wildcards are redundant in positive positions, since they will always be
|
||||
// inferred as necessary there!
|
||||
env.problem(roc_problem::can::Problem::UnnecessaryOutputWildcard {
|
||||
region: loc_ann.region,
|
||||
})
|
||||
}
|
||||
|
||||
ext_type
|
||||
} else {
|
||||
// Report an error but mark the extension variable to be inferred
|
||||
|
|
|
@ -182,6 +182,9 @@ pub enum Problem {
|
|||
original_opaque: Symbol,
|
||||
ability_member: Symbol,
|
||||
},
|
||||
UnnecessaryOutputWildcard {
|
||||
region: Region,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
|
@ -502,7 +502,7 @@ mod solve_expr {
|
|||
Str.fromUtf8
|
||||
"#
|
||||
),
|
||||
"List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]*",
|
||||
"List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3330,7 +3330,7 @@ mod solve_expr {
|
|||
List.get ["a"] 0
|
||||
"#
|
||||
),
|
||||
"Result Str [OutOfBounds]*",
|
||||
"Result Str [OutOfBounds]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3432,7 +3432,7 @@ mod solve_expr {
|
|||
List.get [10, 9, 8, 7] 1
|
||||
"#
|
||||
),
|
||||
"Result (Num *) [OutOfBounds]*",
|
||||
"Result (Num *) [OutOfBounds]",
|
||||
);
|
||||
|
||||
infer_eq_without_problem(
|
||||
|
@ -3441,7 +3441,7 @@ mod solve_expr {
|
|||
List.get
|
||||
"#
|
||||
),
|
||||
"List a, Nat -> Result a [OutOfBounds]*",
|
||||
"List a, Nat -> Result a [OutOfBounds]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3543,7 +3543,7 @@ mod solve_expr {
|
|||
Num.divChecked
|
||||
"#
|
||||
),
|
||||
"Float a, Float a -> Result (Float a) [DivByZero]*",
|
||||
"Float a, Float a -> Result (Float a) [DivByZero]",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3567,7 +3567,7 @@ mod solve_expr {
|
|||
Num.divCeilChecked
|
||||
"#
|
||||
),
|
||||
"Int a, Int a -> Result (Int a) [DivByZero]*",
|
||||
"Int a, Int a -> Result (Int a) [DivByZero]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3591,7 +3591,7 @@ mod solve_expr {
|
|||
Num.divTruncChecked
|
||||
"#
|
||||
),
|
||||
"Int a, Int a -> Result (Int a) [DivByZero]*",
|
||||
"Int a, Int a -> Result (Int a) [DivByZero]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3779,7 +3779,7 @@ mod solve_expr {
|
|||
|
||||
Model position : { openSet : Set position }
|
||||
|
||||
cheapestOpen : Model position -> Result position [KeyNotFound]* | position has Eq
|
||||
cheapestOpen : Model position -> Result position [KeyNotFound] | position has Eq
|
||||
cheapestOpen = \model ->
|
||||
|
||||
folder = \resSmallestSoFar, position ->
|
||||
|
@ -3794,14 +3794,14 @@ mod solve_expr {
|
|||
Set.walk model.openSet (Ok { position: boom {}, cost: 0.0 }) folder
|
||||
|> Result.map (\x -> x.position)
|
||||
|
||||
astar : Model position -> Result position [KeyNotFound]* | position has Eq
|
||||
astar : Model position -> Result position [KeyNotFound] | position has Eq
|
||||
astar = \model -> cheapestOpen model
|
||||
|
||||
main =
|
||||
astar
|
||||
"#
|
||||
),
|
||||
"Model position -> Result position [KeyNotFound]* | position has Eq",
|
||||
"Model position -> Result position [KeyNotFound] | position has Eq",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7498,7 +7498,7 @@ mod solve_expr {
|
|||
r#"
|
||||
OList := [Nil, Cons {} OList]
|
||||
|
||||
lst : [Cons {} OList]*
|
||||
lst : [Cons {} OList]
|
||||
|
||||
olist : OList
|
||||
olist = (\l -> @OList l) lst
|
||||
|
@ -7517,7 +7517,7 @@ mod solve_expr {
|
|||
r#"
|
||||
OList := [Nil, Cons {} OList]
|
||||
|
||||
lst : [Cons {} OList]*
|
||||
lst : [Cons {} OList]
|
||||
|
||||
olist : OList
|
||||
olist = @OList lst
|
||||
|
|
|
@ -1531,7 +1531,7 @@ fn polymorphic_tag() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
x : [Y U8]*
|
||||
x : [Y U8]
|
||||
x = Y 3
|
||||
x
|
||||
"#
|
||||
|
@ -1695,7 +1695,7 @@ fn instantiate_annotated_as_recursive_alias_toplevel() {
|
|||
|
||||
Value : [Nil, Array (List Value)]
|
||||
|
||||
foo : [Nil]*
|
||||
foo : [Nil]
|
||||
foo = Nil
|
||||
|
||||
it : Value
|
||||
|
@ -1723,7 +1723,7 @@ fn instantiate_annotated_as_recursive_alias_polymorphic_expr() {
|
|||
main =
|
||||
Value : [Nil, Array (List Value)]
|
||||
|
||||
foo : [Nil]*
|
||||
foo : [Nil]
|
||||
foo = Nil
|
||||
|
||||
it : Value
|
||||
|
@ -1750,7 +1750,7 @@ fn instantiate_annotated_as_recursive_alias_multiple_polymorphic_expr() {
|
|||
main =
|
||||
Value : [Nil, Array (List Value)]
|
||||
|
||||
foo : [Nil]*
|
||||
foo : [Nil]
|
||||
foo = Nil
|
||||
|
||||
v1 : Value
|
||||
|
|
|
@ -70,7 +70,7 @@ fn num_floor_division() {
|
|||
fn num_floor_checked_division_success() {
|
||||
expect_success(
|
||||
"Num.divTruncChecked 4 3",
|
||||
"Ok 1 : Result (Int *) [DivByZero]*",
|
||||
"Ok 1 : Result (Int *) [DivByZero]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ fn num_floor_checked_division_success() {
|
|||
fn num_floor_checked_division_divby_zero() {
|
||||
expect_success(
|
||||
"Num.divTruncChecked 4 0",
|
||||
"Err DivByZero : Result (Int *) [DivByZero]*",
|
||||
"Err DivByZero : Result (Int *) [DivByZero]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ fn num_ceil_division() {
|
|||
fn num_ceil_checked_division_success() {
|
||||
expect_success(
|
||||
"Num.divCeilChecked 4 3",
|
||||
"Ok 2 : Result (Int *) [DivByZero]*",
|
||||
"Ok 2 : Result (Int *) [DivByZero]",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -380,30 +380,30 @@ fn num_mul_saturated() {
|
|||
#[cfg(not(feature = "wasm"))]
|
||||
#[test]
|
||||
fn num_add_checked() {
|
||||
expect_success("Num.addChecked 1 1", "Ok 2 : Result (Num *) [Overflow]*");
|
||||
expect_success("Num.addChecked 1 1", "Ok 2 : Result (Num *) [Overflow]");
|
||||
expect_success(
|
||||
"Num.addChecked Num.maxI64 1",
|
||||
"Err Overflow : Result I64 [Overflow]*",
|
||||
"Err Overflow : Result I64 [Overflow]",
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "wasm"))]
|
||||
#[test]
|
||||
fn num_sub_checked() {
|
||||
expect_success("Num.subChecked 1 1", "Ok 0 : Result (Num *) [Overflow]*");
|
||||
expect_success("Num.subChecked 1 1", "Ok 0 : Result (Num *) [Overflow]");
|
||||
expect_success(
|
||||
"Num.subChecked Num.minI64 1",
|
||||
"Err Overflow : Result I64 [Overflow]*",
|
||||
"Err Overflow : Result I64 [Overflow]",
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "wasm"))]
|
||||
#[test]
|
||||
fn num_mul_checked() {
|
||||
expect_success("Num.mulChecked 20 2", "Ok 40 : Result (Num *) [Overflow]*");
|
||||
expect_success("Num.mulChecked 20 2", "Ok 40 : Result (Num *) [Overflow]");
|
||||
expect_success(
|
||||
"Num.mulChecked Num.maxI64 2",
|
||||
"Err Overflow : Result I64 [Overflow]*",
|
||||
"Err Overflow : Result I64 [Overflow]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -437,11 +437,11 @@ fn list_sum() {
|
|||
fn list_first() {
|
||||
expect_success(
|
||||
"List.first [12, 9, 6, 3]",
|
||||
"Ok 12 : Result (Num *) [ListWasEmpty]*",
|
||||
"Ok 12 : Result (Num *) [ListWasEmpty]",
|
||||
);
|
||||
expect_success(
|
||||
"List.first []",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]*",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -450,12 +450,12 @@ fn list_first() {
|
|||
fn list_last() {
|
||||
expect_success(
|
||||
"List.last [12, 9, 6, 3]",
|
||||
"Ok 3 : Result (Num *) [ListWasEmpty]*",
|
||||
"Ok 3 : Result (Num *) [ListWasEmpty]",
|
||||
);
|
||||
|
||||
expect_success(
|
||||
"List.last []",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]*",
|
||||
"Err ListWasEmpty : Result a [ListWasEmpty]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -654,18 +654,18 @@ fn type_problem() {
|
|||
|
||||
#[test]
|
||||
fn issue_2149() {
|
||||
expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]*");
|
||||
expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]");
|
||||
expect_success(
|
||||
r#"Str.toI8 "128""#,
|
||||
"Err InvalidNumStr : Result I8 [InvalidNumStr]*",
|
||||
"Err InvalidNumStr : Result I8 [InvalidNumStr]",
|
||||
);
|
||||
expect_success(
|
||||
r#"Str.toI16 "32767""#,
|
||||
"Ok 32767 : Result I16 [InvalidNumStr]*",
|
||||
"Ok 32767 : Result I16 [InvalidNumStr]",
|
||||
);
|
||||
expect_success(
|
||||
r#"Str.toI16 "32768""#,
|
||||
"Err InvalidNumStr : Result I16 [InvalidNumStr]*",
|
||||
"Err InvalidNumStr : Result I16 [InvalidNumStr]",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1155,7 +1155,7 @@ fn box_box_type_alias() {
|
|||
fn issue_2582_specialize_result_value() {
|
||||
expect_success(
|
||||
r#"\x, list -> if x > 0 then List.first list else Ok """#,
|
||||
r"<function> : Num *, List Str -> Result Str [ListWasEmpty]*",
|
||||
r"<function> : Num *, List Str -> Result Str [ListWasEmpty]",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1236,7 @@ fn dict_get_single() {
|
|||
Dict.single 0 {a: 1, c: 2} |> Dict.get 0
|
||||
"#
|
||||
),
|
||||
r#"Ok { a: 1, c: 2 } : Result { a : Num *, c : Num * } [KeyNotFound]*"#,
|
||||
r#"Ok { a: 1, c: 2 } : Result { a : Num *, c : Num * } [KeyNotFound]"#,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1015,6 +1015,15 @@ pub fn can_problem<'b>(
|
|||
title = "OVERLOADED SPECIALIZATION".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
Problem::UnnecessaryOutputWildcard { region } => {
|
||||
doc = alloc.stack([
|
||||
alloc.reflow("I see you annotated a wildcard in a place where it's not needed:"),
|
||||
alloc.region(lines.convert_region(region)),
|
||||
alloc.reflow("Tag unions that are constants, or the return values of functions, are always inferred to be open by default! You can remove this annotation safely."),
|
||||
]);
|
||||
title = "UNNECESSARY WILDCARD".to_string();
|
||||
severity = Severity::Warning;
|
||||
}
|
||||
};
|
||||
|
||||
Report {
|
||||
|
|
|
@ -11731,4 +11731,26 @@ All branches in an `if` must have the same type!
|
|||
denoted with .. - is that what you meant?
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
unnecessary_extension_variable,
|
||||
indoc!(
|
||||
r#"
|
||||
f : {} -> [A, B]*
|
||||
f
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── UNNECESSARY WILDCARD ────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
I see you annotated a wildcard in a place where it's not needed:
|
||||
|
||||
4│ f : {} -> [A, B]*
|
||||
^
|
||||
|
||||
Tag unions that are constants, or the return values of functions, are
|
||||
always inferred to be open by default! You can remove this annotation
|
||||
safely.
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ toHelpHelper = \@Parser parser, configs ->
|
|||
List.append configs (Positional config)
|
||||
|> Config
|
||||
|
||||
findOneArg : Str, Str, MarkedArgs -> Result { val : Str, newlyTaken : Taken } [NotFound]*
|
||||
findOneArg : Str, Str, MarkedArgs -> Result { val : Str, newlyTaken : Taken } [NotFound]
|
||||
findOneArg = \long, short, { args, taken } ->
|
||||
argMatches = \{ index, found: _ }, arg ->
|
||||
if Set.contains taken index || Set.contains taken (index + 1) then
|
||||
|
|
|
@ -2,13 +2,13 @@ interface Stdout
|
|||
exposes [line, write]
|
||||
imports [Effect, Task.{ Task }, InternalTask]
|
||||
|
||||
line : Str -> Task {} * [Write [Stdout]*]*
|
||||
line : Str -> Task {} * [Write [Stdout]]
|
||||
line = \str ->
|
||||
Effect.stdoutLine str
|
||||
|> Effect.map (\_ -> Ok {})
|
||||
|> InternalTask.fromEffect
|
||||
|
||||
write : Str -> Task {} * [Write [Stdout]*]*
|
||||
write : Str -> Task {} * [Write [Stdout]]
|
||||
write = \str ->
|
||||
Effect.stdoutWrite str
|
||||
|> Effect.map (\_ -> Ok {})
|
||||
|
|
|
@ -19,7 +19,7 @@ pushStack = \ctx, data ->
|
|||
# I think an open tag union should just work here.
|
||||
# Instead at a call sites, I need to match on the error and then return the same error.
|
||||
# Otherwise it hits unreachable code in ir.rs
|
||||
popStack : Context -> Result [T Context Data] [EmptyStack]*
|
||||
popStack : Context -> Result [T Context Data] [EmptyStack]
|
||||
popStack = \ctx ->
|
||||
when List.last ctx.stack is
|
||||
Ok val ->
|
||||
|
@ -66,7 +66,7 @@ with = \path, callback ->
|
|||
callback { scopes: [{ data: Some handle, index: 0, buf: [], whileInfo: None }], state: Executing, stack: [], vars: List.repeat (Number 0) Variable.totalCount }
|
||||
|
||||
# I am pretty sure there is a syntax to destructure and keep a reference to the whole, but Im not sure what it is.
|
||||
getChar : Context -> Task [T U8 Context] [EndOfData, NoScope]*
|
||||
getChar : Context -> Task [T U8 Context] [EndOfData, NoScope]
|
||||
getChar = \ctx ->
|
||||
when List.last ctx.scopes is
|
||||
Ok scope ->
|
||||
|
@ -76,7 +76,7 @@ getChar = \ctx ->
|
|||
Err ListWasEmpty ->
|
||||
Task.fail NoScope
|
||||
|
||||
getCharScope : Scope -> Task [T U8 Scope] [EndOfData, NoScope]*
|
||||
getCharScope : Scope -> Task [T U8 Scope] [EndOfData, NoScope]
|
||||
getCharScope = \scope ->
|
||||
when List.get scope.buf scope.index is
|
||||
Ok val ->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue