After reading more I finally came up with a small macro that can be used as a proof of concept, a trivial implementation of the NewType
in Elixir.
While it is not a zero cost abstraction, it is very lightweight and I seriously doubt anyone would run into considerable performance issues using it.
I expanded over the idea of @tomekowal and used tuples, mainly to check for type validation. I am sure there is another way of doing the same is_type?/2
function without using tuples, but I think this is fast enough and the code is clear enough, so no harm done:
defmodule NewType do
defmacro deftype(name, type) do
quote do
defmodule unquote(name) do
@opaque t :: {unquote(name), unquote(type)}
@spec new(value :: unquote(type)) :: t
def new(value), do: {unquote(name), value}
@spec extract(new_type :: t) :: unquote(type)
def extract({unquote(name), value}), do: value
end
end
end
@spec is_type?(data :: {atom, any}, new_type :: atom) :: boolean
def is_type?({type, _data}, new_type) when type == new_type, do: true
def is_type?(_data, _new_type), do: false
end
To see the full context: