Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NTuple, Union, and Parametric Types #15

Open
oyamad opened this issue Jan 18, 2016 · 5 comments
Open

NTuple, Union, and Parametric Types #15

oyamad opened this issue Jan 18, 2016 · 5 comments

Comments

@oyamad
Copy link

oyamad commented Jan 18, 2016

連続で恐縮ですが,また質問です.

IntVector が混ざる可能性のある Tuple を引数に持つ関数を書きたいとします.

julia> function myfunction1{N}(t::NTuple{N,Union{Integer, Vector{Float64}}})
           return t
       end;
julia> myfunction1((1, 2))
(1,2)

julia> myfunction1((1, [2.]))
(1,[2.0])

Vector{Float64} としたので,このままではとうぜん IntegerVector は受け付けてくれない.

julia> myfunction1((1, [2]))
ERROR: MethodError: `myfunction1` has no method matching myfunction1(::Tuple{Int64,Array{Int64,1}})

そこで Vector の type を parametric にして T<:Real にしてみます.

julia> function myfunction2{T<:Real,N}(t::NTuple{N,Union{Integer, Vector{T}}})
           return t
       end;

すると Vector{Int} が入っていても通るようになる.

julia> myfunction2((1, [2.]))
(1,[2.0])

julia> myfunction2((1, [2]))
(1,[2])

しかし,今度は,さっきは通っていた Tuple{Int, Int} を受け付けなくなる.

julia> myfunction2((1, 2))
ERROR: MethodError: `myfunction2` has no method matching myfunction2(::Tuple{Int64,Int64})
Closest candidates are:
  myfunction2{T<:Real,N}(::NTuple{N,Union{Array{T<:Real,1},Integer}})

これはなぜなのでしょうか.

@oyamad
Copy link
Author

oyamad commented Jan 18, 2016

追記:
よく理解していないのですが次のようにしたらうまく動きました.

julia> typealias MyNTuple{T<:Real,N} NTuple{N, Union{Integer, Vector{T}}}
NTuple{N,Union{Array{T<:Real,1},Integer}}

julia> function myfunction3(t::MyNTuple)
          return t
       end;
julia> myfunction3((1, 2))
(1,2)

julia> myfunction3((1, [2]))
(1,[2])

julia> myfunction3((1, [2.]))
(1,[2.0])

何が起きているのでしょうか.

@bicycle1885
Copy link
Member

う〜む、私にはJuliaのバグのように思えます。
function myfunction2{T<:Real,N}(t::NTuple{N,Union{Integer, Vector{T}}})(1, 2)に対しても呼び出せるべきメソッドのように思います。
明日もう少し調べてみます。

以下私が確認した事実のメモです。

以下のように型変数T<:Realを作って、(1, 2)::Tuple{Int,Int}NTuple{2,Union{Integer,Vector{T}}}のインスタンスであることは確認できました。

julia> T = TypeVar(:T, Real, true)
T<:Real

julia> Tuple{Int,Int} <: NTuple{2,Union{Integer,Vector{T}}}
true

julia> isa((1, 1), NTuple{2,Union{Integer,Vector{T}}})
true

しかしメソッド定義にすると、以下のf, g, hは全く呼び出せませんでした。

julia> function f{T<:Real,N}(t::NTuple{N,Union{Integer,Vector{T}}}); t; end
f (generic function with 1 method)

julia> f((1, 2))
ERROR: MethodError: `f` has no method matching f(::Tuple{Int64,Int64})
Closest candidates are:
  f{T<:Real,N}(::NTuple{N,Union{Array{T<:Real,1},Integer}})

julia> function g{T<:Any,N}(t::NTuple{N,Union{Integer,Vector{T}}}); t; end
g (generic function with 1 method)

julia> g((1, 2))
ERROR: MethodError: `g` has no method matching g(::Tuple{Int64,Int64})
Closest candidates are:
  g{T,N}(::NTuple{N,Union{Array{T,1},Integer}})

julia> function h{T,N}(t::NTuple{N,Union{Integer,Vector{T}}}); t; end
h (generic function with 1 method)

julia> h((1, 2))
ERROR: MethodError: `h` has no method matching h(::Tuple{Int64,Int64})
Closest candidates are:
  h{T,N}(::NTuple{N,Union{Array{T,1},Integer}})

型変数Tを省略すれば、以下のiのように呼び出せるようになりました。

julia> function i{N}(t::NTuple{N,Union{Integer,Vector}}); t; end
i (generic function with 1 method)

julia> i((1, 2))
(1,2)

@oyamad
Copy link
Author

oyamad commented Jan 19, 2016

調べていただきありがとうございます.

@bicycle1885
Copy link
Member

もうちょっと問題を狭めていったら、以下の様な簡単な例でもうまく動かないようでした。

function m{T}(t::Union{Int,Vector{T}})
    t
end

function n(t::Union{Int,Vector})
    t
end
julia> m(1)
ERROR: MethodError: `m` has no method matching m(::Int64)
Closest candidates are:
  m{T}(::Union{Array{T,1},Int64})
 in eval at ./boot.jl:265

julia> n(1)
1

どうやら、Unionの中で型変数Tを使う事自体が問題らしく、JuliaのIssuesを見てみても既知の問題として扱われているようです (JuliaLang/julia#3738, https://github.com/JuliaLang/julia/issues/13702)。

ですので、今のところユーザからは解決する手段はなさそうですが、一応後ほどJuliaのIssuesの方にもコメントを残しておこうと思います。

@oyamad
Copy link
Author

oyamad commented Jan 20, 2016

いろいろ調べていただきありがとうございました.
バグというより,難しいから (原理はわかりませんが) 実装しない/できないという感じでしょうか.

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

No branches or pull requests

2 participants