Parametric types and where keyword in Julia v0.6

The following typealias used to work in Julia v0.5:

typealias RealLowerTriangular{T<:Real, S<:AbstractMatrix} LowerTriangular{T, S}

Upon upgrading to Julia v0.6, I received a suggestion on the REPL to use instead the following:

RealLowerTriangular{T<:Real, S<:AbstractMatrix} = LowerTriangular{T, S}

However, trying out the supposed fix yields the following error:

RealLowerTriangular(ones(2))
ERROR: MethodError: Cannot convert an object of type Array{Float64,1} to an object of type LowerTriangular{T,S} where S<:(AbstractArray{T,2} where T) where T<:Real
This may have arisen from a call to the constructor LowerTriangular{T,S} where S<:(AbstractArray{T,2} where T) where T<:Real(…),
since type constructors fall back to convert methods.
Stacktrace:
[1] LowerTriangular{T,S} where S<:(AbstractArray{T,2} where T) where T<:Real(::Array{Float64,1}) at ./sysimg.jl:24

That’s the same in 0.5

julia> typealias RealLowerTriangular{T<:Real, S<:AbstractMatrix} LowerTriangular{T, S}
LowerTriangular{T<:Real,S<:AbstractArray{T,2}}

julia> RealLowerTriangular(ones(2))
ERROR: MethodError: Cannot `convert` an object of type Array{Float64,1} to an object of type LowerTriangular{T<:Real,S<:AbstractArray{T,2}}
This may have arisen from a call to the constructor LowerTriangular{T<:Real,S<:AbstractArray{T,2}}(...),
since type constructors fall back to convert methods.
 in LowerTriangular{T<:Real,S<:AbstractArray{T,2}}(::Array{Float64,1}) at ./sysimg.jl:53

That’s because there was a small typo in my example, sorry. Here is what I meant, which I just tried it in Julia v0.5.2 and it works:

julia> typealias RealLowerTriangular{T<:Real, S<:AbstractMatrix} LowerTriangular{T, S}
LowerTriangular{T<:Real,S<:AbstractArray{T,2}}

julia> RealLowerTriangular(ones(2, 2))
2×2 LowerTriangular{Float64,Array{Float64,2}}:
 1.0   ⋅ 
 1.0  1.0

maybe it’s because ones(2,2) is not lower triangular, and older version had bug?

Thanks Dan, this wasn’t meant to be an accurate example, you are right that ones(2, 2) is not lower triangular. What I am getting at is that the equivalent proposed by Julia v0.6 no longer works, one could use for instance eye(2) above instead of ones(2, 2) to make this point.

Indeed there is a problem getting to the constructor of LowerTriangular from the typedef-ed RealLowerTriangular. A solution can be to define the outer constructor:

# first we do the typedef
RealLowerTriangular{T,S} = LowerTriangular{T,S} where {T<:Real,S<:AbstractMatrix{T}}

# now the outer constructor
RealLowerTriangular(m) = LowerTriangular(m)

The logic is as follows: Calling a constructor is basically calling a method with the type as its name. The outer constructor LowerTriangular is simply a method named LowerTriangular{T,S} where S where T. A RealLowerTriangular is defined as LowerTriangular{T,S} where S<:AbstractMatrix{T} where T<:Real so Julia doesn’t find a method with this name and defaults to the convert constructor for a generic type.

In general, the non-parametrized names of parametric types are equivalent to the types with appropriate where T clauses added (for each parameter).

Hope this somehow makes more sense.
And

julia> RealLowerTriangular(ones(2,2))
2×2 LowerTriangular{Float64,Array{Float64,2}}:
 1.0   ⋅ 
 1.0  1.0

works with these definitions.

Brilliant, this makes sense, and works.