Hi everyone,
I have been trying to write some Julia code in monadic style while keeping it as efficient as possible. I am running in a problem that can be illustrated by the following minimal example:
# Simple implementation of the "list" monad
bind(f, xs) = [ e for x in xs for e in f(x) ]
ret(x) = [x]
function f()
bind([0, 1]) do x
bind([0, 1]) do y
ret((x, y))
end end
end
@assert f() == [(0, 0), (0, 1), (1, 0), (1, 1)]
@code_warntype(f()) # Body::Array{_1,1} where _1...
Here, I wish that the type system could infer the return type of f
(namely Vector{Tuple{Int, Int}}
), which it does not. Note that in the following simpler example, Julia successfully infers the return type of f2
:
function f2()
bind([0, 1]) do x
ret((x, x))
end
end
@code_warntype f2() # Body::Array{Tuple{Int64,Int64},1}...
Can you see any way I can solve this problem?
Edit: I found that it is possible to solve the problem by adding the following type annotations to f
:
function f()
bind([0, 1]) do x
bind([0, 1]) do y
ret((x, y))
end :: Vector{Tuple{Int, Int}}
end :: Vector{Tuple{Int, Int}}
end
@assert f() == [(0, 0), (0, 1), (1, 0), (1, 1)]
@code_warntype(f()) # Body::Array{Tuple{Int64,Int64,Int64},1}
Any idea why these annotations are needed here?