Are regular non-function values allowed in abilities? This example type checks but fails to compile with this compiler error
thread '<unnamed>' panicked at crates/compiler/mono/src/ir.rs:6175:10:
Ability specialization is unknown - code generation cannot proceed!: NoTypeImplementingSpecialization
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
import pf.Stdout
import pf.Task
main =
_ = zero
Stdout.line ""
Arithmetic implements zero : a where a implements Arithmetic
wrapperZero = @NumWrapper 0
NumWrapper a := Num a implements [
Arithmetic {
zero: wrapperZero,
},
]
I feel that I may be running up against the limits of my attempt to hack abilities into being able to represent all of the numeric operations I care about
ah yeah we need a nicer error message for that, but basically every ability member needs to be not only a function, but it also needs to involve an argument which implements that ability
I think a thunk would work though:
Arithmetic implements
zero : {} -> a where a implements Arithmetic
then you just always call it passing {}
Yeah, that should work. Inspect does that with an init method
Oh okay nice. Is this a sign that this is a terrible idea or should I continue and see how it turns out?
And also is there any particular reason why this type checks if it isn’t allowed?
Is this a sign that this is a terrible idea or should I continue and see how it turns out?
Seems fine to try
And also is there any particular reason why this type checks if it isn’t allowed?
Probably cause abilities were added later and no one ever updated the type checker for this.
So it seems like this approach is still causing issues. If I have zero
be a function from a -> a where a implements Arithmetic
then it seems to work fine but I have to pass some dummy value as the argument. But if I have zero
be {} -> a where a implements Arithmetic
I get this error:
thread '<unnamed>' panicked at crates/compiler/mono/src/ir.rs:6164:56:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Example:
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
import pf.Stdout
import pf.Task
main =
_ = zero {}
Stdout.line ""
Arithmetic implements zero : {} -> a where a implements Arithmetic
wrapperZero = \{} -> @NumWrapper 0
NumWrapper a := Num a implements [
Arithmetic {
zero: wrapperZero,
},
]
Hmmm looks like this is an issue with not specifying which concrete type I want the zero
call to produce. Doing this fixes it:
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }
import pf.Stdout
import pf.Task
main =
wrappedZero : NumWrapper a
wrappedZero = zero {}
Stdout.line ""
Arithmetic implements zero : {} -> a where a implements Arithmetic
wrapperZero = \{} -> @NumWrapper 0
NumWrapper a := Num a implements [
Arithmetic {
zero: wrapperZero,
},
]
Not sure how to fix this in the actual context of my usage of this ability though.
Fixed it! The issue was this List, zeroes
, where the compiler wasn't able to infer what implementation of Arithmetic to use for this list (a
implements Arithmetic
here):
mul : Poly a, Poly a -> Poly a
mul = \@Poly a, @Poly b ->
resultLen = (List.len a) + (List.len b) - 1
result = List.withCapacity resultLen
zeroes : List a
zeroes = List.repeat (Arithmetic.zero {}) ((List.len a) + (List.len b) - 1)
List.walkWithIndex zeroes result \acc, _, index ->
inner = List.walkWithIndex (List.range { start: At 0, end: At index }) (Arithmetic.zero {}) \coeff, _, p1Index ->
p2Index = index - p1Index
aCoeff = List.get a p1Index |> Result.withDefault (Arithmetic.zero {})
bCoeff = List.get b p2Index |> Result.withDefault (Arithmetic.zero {})
Arithmetic.add coeff (Arithmetic.add aCoeff bCoeff)
List.append acc inner
|> @Poly
Last updated: Jul 05 2025 at 12:14 UTC