defmodule Tipo do def typeof(value) do typeof_atom(value) end # boolean type checkers def nil?(v), do: is_nil(v) def number?(v), do: is_number(v) def integer?(v), do: is_integer(v) def float?(v), do: is_float(v) def bitstring?(v), do: is_bitstring(v) def atom?(v), do: is_atom(v) def function?(v), do: is_function(v) def boolean?(v), do: is_boolean(v) def binary?(v), do: is_binary(v) def list?(v), do: is_list(v) def map?(v), do: is_map(v) def tuple?(v), do: is_tuple(v) def regex?(v) def regex?(%Regex{}), do: true def regex?(_), do: false def module?(v) do try do :erlang.get_module_info(v) true rescue ArgumentError -> false end end # valid or printable strings def string?(v) do is_binary(v) and (String.printable?(v) or String.valid?(v)) end defp typeof_atom(v) do cond do is_nil(v) -> nil is_number(v) -> :number regex?(v) -> :regex # must come before atom module?(v) -> :module is_boolean(v) -> :boolean # must come before atom b/c booleans are atoms is_atom(v) -> :atom is_binary(v) -> :binary is_bitstring(v) -> :bitstring is_function(v) -> :function is_list(v) -> :list is_tuple(v) -> :tuple is_map(v) -> :map is_pid(v) -> :pid is_port(v) -> :port is_reference(v) -> :reference true -> :non_primitive end end end