-type monad() :: module() | {module(), monad()}.
-type monadic(_M, _A) :: any().
-callback '>>='(monadic(M, A), fun((A) -> monadic(M, B))) -> monadic(M, B) when M :: monad().
-callback fail(any()) -> monadic(M, _A) when M :: monad().
-callback return(A) -> monadic(M, A) when M :: monad().
-spec join(M, monadic(M, monadic(M, A))) -> monadic(M, A).
-spec sequence(M, [monadic(M, A)]) -> monadic(M, [A]).