Skip to content
This repository has been archived by the owner on Feb 7, 2019. It is now read-only.

Subtypes in @traitdef #2

Closed
mindbound opened this issue Nov 16, 2014 · 16 comments
Closed

Subtypes in @traitdef #2

mindbound opened this issue Nov 16, 2014 · 16 comments

Comments

@mindbound
Copy link

How would one write correctly e.g. the following,

@traitdef Foo{X} begin
    fnx{Y <: Integer}(X, Y) -> Integer
end

i.e. so that Y can only be a subtype of Integer? I assume it would require a combination of associated types and @constraints but I can't seem to figure out the details from the documentation. TIA.

@mauro3
Copy link
Owner

mauro3 commented Nov 16, 2014

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!

@mauro3
Copy link
Owner

mauro3 commented Nov 19, 2014

I had a go at using TypeVar. But because of JuliaLang/julia#9043 it still does not work. Will revisit once progress on JuliaLang/julia#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.

@mindbound
Copy link
Author

Thank you for the clarification. I'll keep an eye on this.

mauro3 added a commit that referenced this issue Nov 19, 2014
@mauro3
Copy link
Owner

mauro3 commented Nov 19, 2014

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

@mindbound
Copy link
Author

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?

@mauro3
Copy link
Owner

mauro3 commented Nov 24, 2014

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.

@mindbound
Copy link
Author

Yes, now it's clear to me. For now I'll be sticking with this approach, it seems usable enough.

@mauro3
Copy link
Owner

mauro3 commented Nov 24, 2014

Cool. Thanks for giving Traits.jl a try! It's pretty rough, I'm sure there will be more issues...

@mindbound
Copy link
Author

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.

@mauro3
Copy link
Owner

mauro3 commented Nov 24, 2014

@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.

@mauro3
Copy link
Owner

mauro3 commented Mar 27, 2015

The original example in this issue works, actually for quite a while now, since 92b0b37. So closing.

@mauro3 mauro3 closed this as completed Mar 27, 2015
@mindbound
Copy link
Author

Thank you, very glad to see this fixed/implemented.

@mauro3
Copy link
Owner

mauro3 commented Apr 7, 2015

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 TypeVars: JuliaLang/julia#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...

@mauro3 mauro3 reopened this Apr 7, 2015
mauro3 added a commit that referenced this issue Apr 10, 2015
These two bugs do not matter anymore as the new tests do not rely on method_exists:
method_exists_bug1 = false # see JuliaLang/julia#8959
method_exists_bug2 = false # see JuliaLang/julia#9043 and #2
mauro3 added a commit that referenced this issue Apr 14, 2015
These two bugs do not matter anymore as the new tests do not rely on method_exists:
method_exists_bug1 = false # see JuliaLang/julia#8959
method_exists_bug2 = false # see JuliaLang/julia#9043 and #2
@mauro3 mauro3 closed this as completed in fa5b29e Apr 14, 2015
@mauro3
Copy link
Owner

mauro3 commented Apr 14, 2015

@mindbound, now it is fixed. I replaced all method_exists checks with hand-rolled code.

@mindbound
Copy link
Author

Thank you. Traits.jl is a great addition to Julia, especially coming from a Haskell-ish background.

@mauro3
Copy link
Owner

mauro3 commented Apr 14, 2015

Thanks a lot! Let me know if you find other missing bits or have other comments.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants