I was wondering if there's a way to make something like an Int
type that can only represent a certain subset of numbers (like 0 ~ 29) and have the compiler throw an error if you try to do anything else with it.
I know I could do something like type MoonPhaseDay = Day1|Day2| ... |Day29
but that doesn't scale over a larger range.
I'm trying to keep in mind the advice, "make impossible states impossible to represent". I could get by with an Int
but I'm curious if there's a better way.
What you're looking for is sometimes known as "Dependent Types", and is not part of Elm today.
However, you can get something similar by creating a type in it's own module, and instead of exporting the raw type constructor, only exporting a custom function that you provide (making it an "Opaque Type"). This way, that module contains the only code that has to be guarded.
This answer by Nathan might be helpful when learning about Opaque types.
You'd need to use a smart constructor. You enforce your constraints by controlling what you export from a module.
module Bounded exposing (Bounded, fromInt, toInt)
type Bounded
= Bounded Int
fromInt : Int -> Maybe Bounded
fromInt n =
if n < 0 || n > 29 then
Nothing
else
Just (Bounded n)
toInt : Bounded -> Int
toInt (Bounded n) = n
The Bounded
type is defined as a union type with one data constructor. When exporting the type we don't export the constructor, i.e. it's not part of the public API. This is known as an opaque type.
Users of the module can only ever create Bounded
types using fromInt
. fromInt
is called a smart constructor because it has some logic (the smarts) to enforce the constraints.
If you need to work with the integer it wraps you use toInt
. toInt
is guaranteed to always return an integer between 0 and 29 inclusive. There's no hidden backdoor that would allow any other integer to be wrapped.
The HaskellWiki has a nice write up on smart constructors.
Finally, Richard Feldman in his talk "Types and Tests at The Gilded Rose" goes through a nice example here that explains exactly what you want to do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With