readable

read type class families


License
Apache-2.0

Documentation

Readable

Elixir language have standard String.Chars protocol which describes T -> String relation (like Haskell Show type class). But Elixir don't have any standard protocol for String -> T relation (some equivalent of Haskell Read type class). But I think such protocol completely make sense.

This protocol describes read relation between 2 types. Instance of type B can be read from instance of type A. Usually type A = String, but this implementation don't have this constraint.

Example

import Read

defreadable Integer, from: x :: BitString do
  String.to_integer(x)
end

defreadable URI, from: x :: BitString do
  URI.parse(x)
end

defreadable NaiveDateTime, from: x :: Tuple do
  case NaiveDateTime.from_erl(x) do
    {:ok, y} -> y
    {:error, _} -> fail!(x)
  end
end

and then we can use implementation of Read type class

iex> Read.read("123", Integer)
123

iex> Read.read("https://hello.world", URI)
%URI{
  authority: "hello.world",
  fragment: nil,
  host: "hello.world",
  path: nil,
  port: 443,
  query: nil,
  scheme: "https",
  userinfo: nil
}

iex> Read.read({{2000, 1, 1}, {13, 30, 15}}, NaiveDateTime)
~N[2000-01-01 13:30:15]

iex> Read.read({{2000, 13, 1}, {13, 30, 15}}, NaiveDateTime)
** (Readable.Exception) NaiveDateTime can not be read from {{2000, 13, 1}, {13, 30, 15}}

iex> Read.read("https://hello.world", TypeNotExist)
** (ArgumentError) argument error
    :erlang.binary_to_existing_atom("Elixir.Readable.From.BitString.To.TypeNotExist", :utf8)
    (elixir) src/elixir_aliases.erl:119: :elixir_aliases.safe_concat/1
    (readable) lib/read.ex:84: Read.read/2

Installation

The package can be installed by adding readable to your list of dependencies in mix.exs:

def deps do
  [
    {:readable, "~> 0.2"}
  ]
end