unsafe_cast
So, you want to make an integer type that is not zero.
type NonZeroInt = Int
fn main() {
let n: NonZeroInt = 0
assert n != 0
}
Type aliases will not protect it.
opaque type NonZeroInt {
NonZeroInt(inner: Int)
}
fn from_int(i) {
case i {
0 -> Error(Nil)
_ -> Ok(NonZeroInt(i))
}
}
fn main() {
let assert Error(Nil) = from_int(0)
let assert Ok(_) = from_int(1)
}
Yes, out of all the tools we have, opaque types are the right one. Goodbye.
What? You have a weird internal dynamic type situation where the value needs to be the actual value and not a wrapper around the type? Then you do need this library. (look at the bottom example)
There are probably other usecases of changing the type of a value, but using this library for making inline newtypes will be unneeded if/when it becomes an actual language feature:
- https://github.com/gleam-lang/gleam/issues/637
- https://github.com/gleam-lang/gleam/pull/931
- https://github.com/gleam-lang/gleam/discussions/1398
- https://github.com/gleam-lang/gleam/pull/2330
gleam add unsafe_cast@1
import unsafe_cast
type BinaryInt
fn binary_int_from(int: Int) -> Result(BinaryInt, Nil) {
case int {
0 | 1 ->
Ok(
unsafe_cast.unsafe_function_that_simply_renames_the_type_of_this_value_to_another_type_and_i_am_sure_that_this_usage_is_safe(
int,
),
)
_ -> Error(Nil)
}
}
fn binary_int_to(bin_int: BinaryInt) -> Int {
unsafe_cast.unsafe_function_that_simply_renames_the_type_of_this_value_to_another_type_and_i_am_sure_that_this_usage_is_safe(
bin_int,
)
}
Further documentation can be found at https://hexdocs.pm/unsafe_cast.
Development
gleam run # Run the project
gleam test # Run the tests