Can type specs express algebraic data types?

Hello,
I have the following piece of code and I’d like to annotate it with a type spec but I’m not sure what would be the best way to do it.

  def get(url) do
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        {:ok, extract_data(body) }
      {:ok, %HTTPoison.Response{status_code: 404}} -> {:error, "Not found"}
      {:error, %HTTPoison.Error{reason: reason}} -> {:error, reason}
    end

end

The implementation of extract_data is not important. What I’d like to be able to express is that this function either returns {:ok, data} or {:error, reason}. Is it possible to write a type spec for that?

In this case I cannot just “let it crash” and care only about the happy path because the url is coming from the user and I want to be able to either give the user the data it needs or return a message detailing what went wrong.

3 Likes

hi @mariosangiorgio,

yes, of course you can. it’s widely used, and this is the “OR” operator |

@type url :: binary
@type reason :: binary
@type data :: term

@spec get(url) :: {:ok, data} | {:error, reason}
def get(url) do
...
5 Likes

Thanks!

2 Likes