# No method matching error when calling generic constructor with concrete implementer of abstract type

**URL:** https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192
**Category:** New to Julia
**Tags:** question
**Created:** [January 12, 2021, 10:56am UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192 "2021-01-12T10:56:32Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 10:56am UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/1 "2021-01-12T10:56:33Z")

</div>

I am trying to implement several algorithms that share a branch-and-bound setup on top, but have different sub problems. To do this, I decided to create abstract types for the sub problems and make the branch-and-bound type generic, but I get an error that I just do not understand at all.

Here is a minimal reproduction of the problem:

```julia
struct Dataset
end
struct Duals
end

# === ABSTRACT FACTORY TYPE ===
abstract type SubProblemFactory end
abstract type SubProblem end

function make_sub_problem(factory::SubProblemFactory,
                          dataset::Dataset,
                          duals::Duals)::SubProblem
  error("make_sub_problem was not implemented")
end

# === CONCRETE IMPL ===
struct MySubProblemFactory <: SubProblemFactory
end

function make_sub_problem(factory::MySubProblemFactory,
                          dataset::Dataset,
                          duals::Duals)::MySubProblem
  MySubProblem(dataset, duals)
end

mutable struct MySubProblem <: SubProblem
  dataset :: Dataset
  duals :: Duals
end

# === HOLDS A SUB PROBLEM FACTORY ===
struct BranchAndBound{F <: SubProblemFactory}
  factory :: F
  dataset :: Dataset

  function BranchAndBound{F}(factory::F, dataset::Dataset) where F<:SubProblemFactory
    new(factory, dataset)
  end
end

function solve()
  dataset = Dataset()
  factory = MySubProblemFactory()
  bb = BranchAndBound(factory, dataset)
end

solve()

```

```nohighlight
ERROR: LoadError: MethodError: no method matching BranchAndBound(::MySubProblemFactory, ::Dataset)
Stacktrace:
 [1] solve() at /tmp/test.jl:44
 [2] top-level scope at /tmp/test.jl:47
in expression starting at /tmp/test.jl:47

```

Where have I gone wrong here? The method clearly exists, as the constructor is defined for any subtype of `SubProblemFactory`, and `MySubProblemFactory` is indeed defined to be a subtype of that.

---

<div class="post-metadata">

### Author: ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)
#### Post date: [January 12, 2021, 12:19pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/2 "2021-01-12T12:19:20Z")

</div>

Not sure, but I think you need to specify the type parameter to `BranchAndBound` in `solve()`

Edit:

```julia
julia> methods(BranchAndBound)
# 0 methods for type constructor:

julia> methods(BranchAndBound{MySubProblemFactory})
# 1 method for type constructor:
[1] (::Type{BranchAndBound{F}})(factory::F, dataset::Dataset) where F<:SubProblemFactory in Main at REPL[9]:6

```

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [January 12, 2021, 12:19pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/3 "2021-01-12T12:19:55Z")

</div>

This works:

```julia
julia> abstract type SubProblemFactory end

julia> struct MySubProblemFactory <: SubProblemFactory
       end

julia> struct BranchAndBound{F <: SubProblemFactory}
        BranchAndBound(f::F) where F<:SubProblemFactory = new{F}()
       end

julia> f = MySubProblemFactory()
MySubProblemFactory()

julia> BranchAndBound(f)
BranchAndBound{MySubProblemFactory}()

julia>

```

I think there is some problem with the way you defined the constructor. (the `new{F}`, the type parameter is missing there, as pointed above, I think that is the problem).

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 12:22pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/4 "2021-01-12T12:22:44Z")

</div>

Thanks. This worked:

```julia
function solve()
  dataset = Dataset()
  factory = MySubProblemFactory()
  bb = BranchAndBound{MySubProblemFactory}(factory, dataset)
end

```

The `new{F}` does not appear to be necessary.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [January 12, 2021, 12:25pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/5 "2021-01-12T12:25:57Z")

</div>

> [@alice](#):
>
> The `new{F}` does not appear to be necessary.

Yes, in one case you need to define the type parameter explicitly on construction, in the `new{F}` case, it is deduced from the type of the argument:

```julia
julia> struct A{T}
         i
       end

julia> A(1) # does not work
ERROR: MethodError: no method matching A(::Int64)
Stacktrace:
 [1] top-level scope at REPL[2]:1

julia> A{Int64}(1) # explicitly defining the type parameter
A{Int64}(1)

julia> A(i::T) where T = A{T}(i) # deduces type from argument
A

julia> A(1) # now it works
A{Int64}(1)

julia>

```

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 12:32pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/6 "2021-01-12T12:32:12Z")

</div>

It seems like this is a prime case for improving the error messages in Julia.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [January 12, 2021, 12:32pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/7 "2021-01-12T12:32:32Z")

</div>

Agreed.

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [January 12, 2021, 2:04pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/8 "2021-01-12T14:04:44Z")

</div>

I can’t help but notice that the code is very Java-esque.  
In Julia, you normally can do without factories and just directly use a type constructor instead:

```julia
function make_sub_problem(sptype::Type{MySubProblem},
                          dataset::Dataset,
                          duals::Duals)
  MySubProblem(dataset, duals)
end

function make_sub_problem(sptype::Type{AnotherSubProblem},
                          dataset::Dataset,
                          duals::Duals)
  # implementation for AnotherSubProblem
end

```

Calls will look like

```julia
make_sub_problem(MySubProblem, dataset, duals)

```

The first argument is a `DataType`, not an instance of that type.

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 2:10pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/9 "2021-01-12T14:10:30Z")

</div>

Ah, interesting. In the spirit of [this question](https://discourse.julialang.org/t/meaning-and-error-message-of-type-parameters/53198), it doesn’t seem like you even need to keep the `sptype` value around at all? Just make the struct be parameterized and don’t include any fields that mention the type.

As for Java, my most familiar language is Rust, and Rust even supports that pattern you mentioned, although you wouldn’t keep the type object around like I suggested. I just didn’t know enough Julia to know how to do that. In fact, you’ll find me on the Rust discourse, answering questions like you are doing here.

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 2:20pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/10 "2021-01-12T14:20:45Z")

</div>

Hmm, maybe you do need the type object? This gives a weird error:

```julia
struct Dataset
end
struct Duals
end

# === ABSTRACT FACTORY TYPE ===
abstract type SubProblem end

function make_sub_problem{T}(dataset::Dataset, duals::Duals) where T <: SubProblem
  error("oops")
end

```

```nohighlight
ERROR: LoadError: UndefVarError: make_sub_problem not defined
Stacktrace:
 [1] top-level scope at /tmp/test.jl:9
in expression starting at /tmp/test.jl:9

```

Like, yes, `make_sub_problem` is not yet defined? I’m in the progress of defining it?..

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [January 12, 2021, 2:38pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/11 "2021-01-12T14:38:27Z")

</div>

Right, functions cannot be explicitly parameterized in Julia, unlike C++ or Rust.

You can make a callable “factory” type of course. That will work just the same as a function but looks kind of foreign to Julia:

```julia
function make_sub_problem(T::Type{<:SubProblem}, dataset::Dataset, duals::Duals)
    T(dataset, duals)
end

subproblem = make_sub_problem(MySubProblem, dataset, duals)

# or
struct SubProblemFactory{T<:SubProblem} end

(::SubProblemFactory{T})(dataset::Dataset, duals::Duals) where {T}
    T(dataset, duals)
end

factory = SubProblemFactory{MySubProblem}()
subproblem = factory(dataset, duals)

```

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 2:40pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/12 "2021-01-12T14:40:07Z")

</div>

Right, using a Type object seems a lot more natural than that. I’m still very confused about the error message though — why do I get an `UndefVarError` of all things?

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [January 12, 2021, 2:49pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/13 "2021-01-12T14:49:18Z")

</div>

Ah, right. Because the parser thinks you want to define an external type constructor `make_sub_problem{T}(a, b)` for a non-existing type. My previous example can actually be modified as follows:

```julia
struct SubProblemFactory{T<:SubProblem} end

function SubProblemFactory{T}(dataset::Dataset, duals::Duals) where {T}
    T(dataset, duals)
end

subproblem = SubProblemFactory{MySubProblem}(dataset, duals)

```

It’s weird / crazy that a constructor is allowed to return anything at all, not necessarily the type in its name, but it is how things are.

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 2:55pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/14 "2021-01-12T14:55:54Z")

</div>

So it thought I was trying to define a constructor… I’m not particularly impressed with these error messages.

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 3:01pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/15 "2021-01-12T15:01:45Z")

</div>

Wait, doesn’t this mean I could still call the constructor of `T` without having a separate factory type?

---

<div class="post-metadata">

### Author: ![alice](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alice/32/20895_2.png) [@alice](https://discourse.julialang.org/u/alice)
#### Post date: [January 12, 2021, 3:14pm UTC](https://discourse.julialang.org/t/no-method-matching-error-when-calling-generic-constructor-with-concrete-implementer-of-abstract-type/53192/16 "2021-01-12T15:14:48Z")

</div>

Haha! It works.

```julia
struct Dataset
end
struct Duals
end

# === ABSTRACT FACTORY TYPE ===
abstract type SubProblem end

# === CONCRETE IMPL ===
mutable struct MySubProblem <: SubProblem
  dataset :: Dataset
  duals :: Duals

  function MySubProblem(dataset::Dataset, duals::Duals)
    println("success!")
    new(dataset, duals)
  end
end

# === HOLDS A SUB PROBLEM FACTORY ===
struct BranchAndBound{F <: SubProblem}
  dataset :: Dataset

  function BranchAndBound{F}(dataset::Dataset) where F<:SubProblem
    new(dataset)
  end
end

function foo_bb(bb::BranchAndBound{F}) where F<:SubProblem
  sub = F(bb.dataset, Duals())
end

function solve()
  dataset = Dataset()
  bb = BranchAndBound{MySubProblem}(dataset)
  foo_bb(bb)
end

solve()

```

```julia
success!

```
