Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type parameters and inner constructors in julia 0.6

Tags:

julia

I am in doubt about how to restrict type parameters for parametric types with abstract types in julia 0.6, using the where syntax.

Consider the example where I want to make a parametric abstract type that takes integers, and define structs inheriting from that. If I try:

abstract type AbstractFoo{T} where T<: Integer end

it fails, but instead I can use the non-where syntax

abstract type AbstractFoo{T<:Integer} end
  1. Is this the recommended format?

Given this, how do I implement my subtype

mutable struct Foo{T} <: AbstractFoo{T} where T <: Integer
   bar::T
end

fails too (Invalid subtyping). I can bypass the where syntax again with

mutable struct Foo{T<:Integer} <: AbstractFoo{T}
   bar::T
end

But that seems to be redundant (because T is already restricted to be an Integer). 2. Could I leave it out?:

mutable struct Foo{T} <: AbstractFoo{T}
    bar::T
end

Finally, with the deprecation of inner constructor syntax, is there any way around defining the inner constructor as:

mutable struct Foo{T} <: AbstractFoo{T}
    bar::T
    Foo{T}(x::T) where T = new(x)
end

This makes Foo(3) impossible - requiring me to use Foo{Int}(3). 3. Is this intentional or is there a better way around this? EDIT: I guess for the inner constructor question I can always define an outer constructor Foo(x::T) where {T} = Foo{T}(x).

like image 668
Michael K. Borregaard Avatar asked May 30 '17 12:05

Michael K. Borregaard


2 Answers

I would write:

abstract type AbstractFoo{T<:Integer} end

mutable struct Foo{T} <: AbstractFoo{T}
    bar::T
    Foo(x::T) where T = new{T}(x)
end

this 1) limit x to Integer 2) allow write Foo(2)

About the questions:

  1. yes, that the right and only right format
  2. that's valid and T will be restrict to Integer, but you may get a worse error message since it is arised from AbstractFoo, not Foo. Your user may not notice that Foo is a subtype of AbstractFoo and get confused.
  3. This is intended and is one of the main purposes of introducing where syntax. In the new syntax, T{S} always specify the type parameter of T and where S is introducing type parameter of the function. So Foo{T}(x) where T = defines what Foo{Int}(2) should do, and Foo(x::T) where T = defines what Foo(2) should do. After where was introduced, there are no "inner constructor" anymore. You can define any function inside any struct (not necessarily constructors of that type), and define any constructor outside type definition - the only difference is inside type definition, you have access of new.
like image 64
张实唯 Avatar answered Nov 04 '22 09:11

张实唯


I am on slightly shaky ground here, but I had a similar question not long ago. Based on what I learned from that, I suggest that you try this and see how it works for you:

abstract type AbstractFoo{T} end

mutable struct Foo{T<:Integer} <: AbstractFoo{T}
    bar::T
end

It seems most reasonable to me to restrict the parameter on the concrete type rather than on the abstract one.

like image 43
DNF Avatar answered Nov 04 '22 09:11

DNF