Elixir has optional typing though. You can type check with Erlang's Dialyzer.
I don't know if the Erlang/Dialyzer docs cover that specifically, but I know the originial paper on Dialyzer and Dialyzer type specs does.
@type pair(t, u) :: {t, u}
@type result(t, e) :: {:ok, t} | {:error, e}
I'm more talking about type parameters on functions, and also constraining by behaviors and protocols. For example the typespec for Elixir's Stream.map/2 (http://elixir-lang.org/docs/stable/elixir/Stream.html#map/2): @spec map(Enumerable.t, (element -> any)) :: Enumerable.t
Note all the other similarly unspecific type definitions. In a parametrically polmorphic lang, you could do something like: @spec map[e1: Enumerable, e2: Enumerable](e1.t, (e1.element -> e2.element)) :: e2.t
And perhaps even intersections of behaviours and protocols: @spec foo[a: Eq & Ord](a.t, a.t) :: bool
('scuse the Elixir syntax...)