In Elixir, how can I document that a function will return a module that implements a specific behavior?
To use a trivial example, let's say I created a GreeterBehaviour behavior that is implemented by two modules:
defmodule GreeterBehaviour do @callback say_hello(String.t) :: String.t end defmodule FormalGreeter do @behaviour GreeterBehaviour def say_hello(name) do "Good day to you #{name}" end end defmodule CasualGreeter do @behaviour GreeterBehaviour def say_hello(name) do "Hey #{name}" end end
Then I want to easily change any of these implementations, getting Greeter through a function:
defmodule MyApp do def main do greeter().say_hello("Pete") |> IO.puts end @spec greeter() :: GreeterBehaviour # This doesn't work with dialyzer def greeter do FormalGreeter # Can easily be swapped to CasualGreeter end end
Dialyzer will successfully verify that both CasualGreeter and FormalGreeter correctly implement GreeterBehaviour behavior. However, how can I define typepec so that Dialyzer checks that greeter/0 returns a module that actually implements GreeterBehaviour ?
Using @spec greeter() :: GreeterBehaviour does not work, as Dialyzer will give a warning:
lib/my_app.ex:19: Invalid type specification for function 'Elixir.MyApp':greeter/0. The success typing is () -> 'Elixir.FormalGreeter'
source share