Closed mindbound closed 9 years ago
Yes, parameterized functions signatures are not allowed in the trait definition. It's not possible to store them in the naive way I'm doing this at the moment: a Dict Function -> type-tuples. Methods actually use TypeVar
for storing their signature. So maybe I should try that too but documentation on TypeVar
is a bit sparse. Anyway, this works:
@traitdef Foo{X} begin
fnx(X, Integer) -> Integer
end
fnx(a::ASCIIString, b::Integer) = 5
@assert istrait(Foo{ASCIIString}, verbose=true)
Note that fnx(a::ASCIIString, b::Int) = ...
wouldn't work. Not sure how to do it best with invariant containers like arrays though. Any ideas welcome!
I had a go at using TypeVar. But because of https://github.com/JuliaLang/julia/issues/9043 it still does not work. Will revisit once progress on https://github.com/JuliaLang/julia/issues/8974 is made, or if I fancy putting my own method_exits
together.
There are tests at https://github.com/mauro3/Traits.jl/blob/master/test/traitdef.jl#L167 which illustrate what works and what doesn't.
Thank you for the clarification. I'll keep an eye on this.
I added an example with a work-around. Maybe something along the lines you were thinking in the original post: https://github.com/mauro3/Traits.jl/blob/master/examples/ex_issue2.jl
Thank you, I'll take a look at it (though more bulky, perhaps this can do the work until the two issues are fixed and you can update your code).
One question though: Given that # tf89(2., Int[1,2]) # errors
, shouldn't the declaration be Foo{Integer}
instead of Foo{Int}
in https://github.com/mauro3/Traits.jl/blob/master/examples/ex_issue2.jl#L30 and https://github.com/mauro3/Traits.jl/blob/master/examples/ex_issue2.jl#L58, or am I misreading something?
tf89(2., Int[1,2]) # errors
because Foo{Float64}
is only defined to work with Vector{UInt8}
, see: https://github.com/mauro3/Traits.jl/blob/master/examples/ex_issue2.jl#L25. Although why I put that there escapes me. Does this answer your question?
Anyway, I did a small update so the impls can have type constraint functions. Have a look at the last traitimpl in the example.
Yes, now it's clear to me. For now I'll be sticking with this approach, it seems usable enough.
Cool. Thanks for giving Traits.jl a try! It's pretty rough, I'm sure there will be more issues...
That's fine, especially given that much of Julia itself is pretty experimental for the time being.
One related-ish question: how do we stand on subtyping the traitimpls themselves (i.e. @traitimpl Foo{X <: Bar}
)? I can't seem to find any hints in the source or docs.
@traitimpl Foo{X <: Bar} begin ...
, yep, I guess this could be nice in some instances. But I'll wait for JuliaLang/julia#8974 to clear.
The original example in this issue works, actually for quite a while now, since 92b0b376. So closing.
Thank you, very glad to see this fixed/implemented.
Sorry, I was wrong! Whilst it is no error to define:
@traitdef Foo{X} begin
fnx{Y <: Integer}(X, Y) -> Integer
end
it doesn't work:
julia> fnx{Y<:Integer}(x::Int, y::Y) = 1
fnx (generic function with 1 method)
julia> istrait(Foo{Int}, verbose=true)
Method fnx with call signature (Int64,Y<:Integer) not defined for Foo{Int64}
false
because method_exists
doesn't work with TypeVar
s: https://github.com/JuliaLang/julia/issues/9043
This is in fact what I wrote above but for some reason I thought it was fixed after all. Sorry, I'm just getting up to speed with this again and was a bit confused...
@mindbound, now it is fixed. I replaced all method_exists
checks with hand-rolled code.
Thank you. Traits.jl is a great addition to Julia, especially coming from a Haskell-ish background.
Thanks a lot! Let me know if you find other missing bits or have other comments.
How would one write correctly e.g. the following,
i.e. so that
Y
can only be a subtype ofInteger
? I assume it would require a combination of associated types and@constraint
s but I can't seem to figure out the details from the documentation. TIA.