The Available Types

You can define implementations for one or more of the following types:

Any

Atom

BitString

Float

Function

Integer

List

Map

PID

Port

Record

Reference

Tuple

The type BitString is used in place of Binary.

The type Any is a catchall, allowing you to match an implementation with any type. Just as with function definitions, you’ll want to put the implementations for specific types before an implementation for Any.

You can list multiple types on a single defimpl. For example, the following protocol can be called to determine whether a type is a collection:

protocols/is_collection.exs
 defprotocol​ Collection ​do
  @fallback_to_any true
 def​ is_collection?(value)
 end
 
 defimpl​ Collection, ​for:​ [List, Tuple, BitString, Map] ​do
 def​ is_collection?(_), ​do​: true
 end
 
 defimpl​ Collection, ​for:​ Any ​do
 def​ is_collection?(_), ​do​: false
 end
 
 Enum.each [ 1, 1.0, [1,2], {1,2}, %{}, ​"​​cat"​ ], ​fn​ value ->
  IO.puts ​"​​#{​inspect value​}​​: ​​#{​Collection.is_collection?(value)​}​​"
 end

We write defimpl stanzas for the collection types: List, Tuple, BitString, and Map. But what about the other types? To handle those, we use the special type Any in a second defimpl. If we use Any, though, we also have to add an annotation to the protocol definition. That’s what the @fallback_to_any line does.

This produces

 1: false
 1.0: false
 [1,2]: true
 {1,2}: true
 %{}: true
 "cat": true