# Proposal: Defining custom numeric types

**URL:** <https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510>\
**Category:** Request Feedback\
**Created:** [April 11, 2020, 5:04am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510 "2020-04-11T05:04:50Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 11, 2020, 5:04am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/1 "2020-04-11T05:04:50Z")

</div>

**Edit: see [this](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/12) reply**

* * *

Elm has built-in typeclasses like `number` and `comparable` (maybe they aren’t actually called typeclasses). For example, `number` means that the value can either be `Int` or `Float`.

I don’t think there is currently any need to be able to define custom typeclasses, but the ability to extend the built-in ones would be very useful.

Typeclasses in Elm basically define what operators are supported by a type. For example, the `number` typeclass includes all types that support `+`, `-`, and other arithmetic operators. Extending these typeclasses allows us to make custom types work with the built-in operators.

What this means is that typeclasses could be extended by simply defining the functions that implement these operators. For example, here is a type that represents a fraction:

```auto
module Fraction exposing (..)
type alias Fraction =
    { numerator : Int
    , denominator : Int
    }

```

Currently, there is no way to make it possible to do `fraction1 + fraction2`; we have to do `Fraction.add fraction1 fraction2` (`Fraction` is a module). This is very verbose. Another problem is that we can’t pass a `Fraction` as an argument to functions like `List.sum`.

Like I said earlier, Elm typeclasses define what operators a type supports. I think it should be possible for a custom type to extend a typeclass simply by defining a function for all of the necessary operators. It would be done with something like this:

```auto
-- Fraction refers to a type
Fraction.compare : Fraction -> Fraction -> Order
Fraction.compare a b =
    -- ...

```

Defining the function shown above would automatically make `Fraction` a `comparable` type. So now we can do things like `fraction1 < fraction2`. More importantly, we can do `min fraction1 fraction2` without having to redefine `min`.

There should also be a syntax for explicitly saying that a type is part of a typeclass. It needs to work well with types that use type variables. Maybe something like this:

```auto
type alias Fraction [comparable, number] =
    -- ...

```

What do you think of this idea?

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [April 11, 2020, 5:56am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/2 "2020-04-11T05:56:12Z")

</div>

> [@DullBananas](#):
>
> What do you think of this idea?

The general idea here is [Abstract Data type](https://en.wikipedia.org/wiki/Abstract_data_type) and there have been talks about bringing something like this into Elm since forever. There is a [meta-issue](https://github.com/elm/compiler/issues/1039) that captures more information (it links to other issues where discussions about various options happened). As you can see in that issue, the first discussion about this was in 2012.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 11, 2020, 4:56pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/3 "2020-04-11T16:56:51Z")

</div>

What I am actually referring to here is constrained type variables; that’s what they are referred to [here](https://guide.elm-lang.org/types/reading_types.html). It might also be useful to add a new constrained type variable called `list` that includes things like `Array`, `List`, and `String`. For this, it might only be necessary to define the implementation of the cons `::` operator to make a new `list` type work with things like `List.foldl` and `List.filter`.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 11, 2020, 6:28pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/4 "2020-04-11T18:28:35Z")

</div>

For extending `number` to work, we might have to merge `/` and `//` to a single `/` operator that works with any `number` as long as they have the same type.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 11, 2020, 6:52pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/5 "2020-04-11T18:52:35Z")

</div>

I made a full example [here](https://gist.github.com/dullbananas/abbf4f630f2682b5b08e4b65faad896e)

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 5:13am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/6 "2020-04-12T05:13:29Z")

</div>

This would mostly benefit libraries that define custom numeric types. A good example is the [Quantity](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Quantity) type in elm-units. It defines many convenience functions like `max` and `abs`. If it were possible to extend `number`, and the elm-units package utilized this feature, then it would not have to redefine these convenience functions because the ones in the core libraries would work. It’s also worth mentioning that `number` is a superset of `comparable`

---

<div class="post-metadata">

**Author:** ![MartinS](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/martins/32/3137_2.png) [@MartinS](https://discourse.elm-lang.org/u/MartinS)\
**Post date:** [April 12, 2020, 7:16am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/7 "2020-04-12T07:16:07Z")

</div>

If you combine `/` and `//` then what’s the result of `5 / 2`? Is it `2.5` or is it `2`?

---

<div class="post-metadata">

**Author:** ![lpil](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lpil/32/3139_2.png) [@lpil](https://discourse.elm-lang.org/u/lpil)\
**Post date:** [April 12, 2020, 9:33am UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/8 "2020-04-12T09:33:17Z")

</div>

> [@MartinS](#):
>
> If you combine `/` and `//` then what’s the result of `5 / 2` ? Is it `2.5` or is it `2` ?

It could be either. It’s a matter of API design mostly.

I would suggest that returning an Int makes sense in this case.

```auto
(/) : Comparable t => t -> t -> t

```

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 4:47pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/9 "2020-04-12T16:47:20Z")

</div>

If type annotations are used to define what 5 and 2 are then this isn’t a problem. In this case, there needs to be a way to be explicit about the types of 5 and 2. Maybe if their types aren’t defined with a type annotation then it should figure it out based on whether or not there is a decimal point:

```auto
5 / 2 == 2
5.0 / 2.0 == 2.5

```

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 4:48pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/10 "2020-04-12T16:48:24Z")

</div>

@lpil what does the `Comparable t =>` mean

---

<div class="post-metadata">

**Author:** ![pd-andy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pd-andy/32/4145_2.png) [@pd-andy](https://discourse.elm-lang.org/u/pd-andy)\
**Post date:** [April 12, 2020, 5:52pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/11 "2020-04-12T17:52:51Z")

</div>

It’s a constraint, it says type `t` is a member of the `Comparable` type class.

Honestly, as @pdamoc pointed out, this discussion has been rehashed for nearly a decade now. It’s safe to say if there was enough interest in bringing typeclasses to elm, it would’ve happened by now.

The trend of elm’s development of the last few versions has been to _take things away_ and reduce complexity; typeclasses add that complexity back and “my code is more verbose without them” isn’t a particularly persuasive argument.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 6:19pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/12 "2020-04-12T18:19:14Z")

</div>

Good point. Simplicity is what makes Elm very special and fun to use. That’s why I did not propose the ability to define custom typeclasses. In fact, now that you have mentioned reducing Elm’s complexity, I think it should only be possible to extend the `number` typeclass. I don’t see any practical use case for extending things like `appendable`, and I no longer think there should be a `list` typeclass because of how different variants of list have slightly different behavior.

**Now I am only proposing the ability to define custom numeric types.**

Now that I am thinking of this proposal differently, maybe the syntax for making a custom numeric type should be different.

Declaring that a type is a numeric type would look like this:

```auto
numeric type Fraction =
    { ... }

```

Numeric types have to implement five functions: addition, subtraction, multiplication, division, and compare. Maybe the syntax for defining these functions could look something like this:

```auto
mumeric add : Fraction -> Fraction -> Fraction
fraction1 + fraction2 =
    -- ...

numeric compare : Fraction -> Fraction -> Order
compare fraction2 fraction2 =
    -- ...

```

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 6:31pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/13 "2020-04-12T18:31:13Z")

</div>

Also I no longer think `/` and `//` should be merged. `//` should be for `Int`, and `/` should be for all other `number` types, including custom ones.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 12, 2020, 9:55pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/14 "2020-04-12T21:55:28Z")

</div>

For types like the `Quantity` type in [elm-units](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/), there should be a way to only have to implement a `map` function to make it a `number`. This is how `Quantity` is defined:

```auto
type Quantity number units
    = Quantity number

```

For this, defining `numeric map` would be the only function needed to make it a `number`:

```auto
numeric map : ( number -> number ) -> Quantity number u -> Quantity number u
map func ( Quantity value ) =
    Quantity <| func value

```

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [April 13, 2020, 8:19pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/15 "2020-04-13T20:19:36Z")

</div>

Actually maybe whole thing isn’t a good idea. Quantity in elm units is too different from normal numbers and [having a map function could cause type safety to be lost.](https://github.com/ianmackenzie/elm-units/issues/48#issuecomment-612887402). If there is many practical use cases for using fractions, it should be part of the core library.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [April 23, 2020, 8:19pm UTC](https://discourse.elm-lang.org/t/proposal-defining-custom-numeric-types/5510/16 "2020-04-23T20:19:39Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
