Stream: ideas

Topic: Numeric abilities


view this post on Zulip Richard Feldman (Mar 15 2022 at 01:10):

I realized a design problem with having one Arithmetic ability covering everything, instead of individual abilities like Addition and Division: backwards compatibility

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:13):

if there's an Arithmetic ability, and all the functions are expressed in terms of Num (which is an alias for a | a supports Arithmetic) then that means the ability's required functions must not only be the basic arithmetic ones, but also others like mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]*

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:14):

that in turn means that if we want to add a new function like that to Num in the future, it has to be added to the ability too, which means every custom numeric type will become invalid because they won't implement that

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:14):

(unless we also introduce the possibility of abilities having default implementations, but even then, that only works if the new operation happens to be expressible in terms of existing ones)

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:15):

actually I guess there could still be Arithmetic, but maybe it only covers the basic arithmetic and comparison ops that have infix operators, like +, -, >, <, etc.

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:16):

but then all the others, like addSaturated : Num a, Num a -> Num a would live in Num but outside the ability

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:16):

so that would mean if I added a Complex type for complex numbers, I'd call Complex.addSaturated instead of Num.addSaturated, but I could still use +

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:17):

and then if in the future Num introduced a new top-level function intended to be called fully-qualified (e.g. Num.whatever), that wouldn't affect the Arithmetic ability

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:17):

so nothing would break

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:18):

that might mean Num would have to become an opaque type, and Int an alias for it

view this post on Zulip Richard Feldman (Mar 15 2022 at 01:18):

and add would have to become Num.add : a, a -> a | a supports Arithmetic

view this post on Zulip Sampo Vuori (Mar 15 2022 at 02:10):

Hmm, I guess this has something to do with why Haskell has a hierarchy of typeclasses that are based on mathematical features that different categories have (semiring, ring, monoid etc)

view this post on Zulip Richard Feldman (Mar 15 2022 at 02:11):

I think that's unrelated :big_smile:

view this post on Zulip Richard Feldman (Mar 15 2022 at 02:12):

a better example might be Rust's Add trait for addition

view this post on Zulip Richard Feldman (Mar 15 2022 at 02:12):

it's very granular!

view this post on Zulip Richard Feldman (Mar 15 2022 at 03:09):

ok, I figured out a design that seems nice - basically in order to support any of the arithmetic infix operators, you have to support (roughly) all of them, but you don't have to support any other operations.

view this post on Zulip Richard Feldman (Mar 15 2022 at 03:15):

the Num and Int types work the same way they do today, but the type signatures for the functions that infix operators desugar to look different - e.g. Num.add becomes add : a, a -> a | a supports Arithmetic, which seems reasonable since the docs for Arithmetic explain that Num is compatible with it


Last updated: Jun 16 2026 at 16:19 UTC