No signature match between same type across different modules

I have the following (simplified) module structure in my program.

modules-2

I have also detailed the simplified structure of each module.

module Entities
    export Agent, Space
    struct Agent
        .
    end
    struct Space
        .
    end
end
module Loader
    export load_data, read_config
    include("./entities.jl")
    using .Entities: Agent, Space

    function read_config(...)
        .
    end
    function load_data(...)::Tuple{Vector{Space}, Vector{Agent}}
        .
    end
end
module Scheduler
    include("./loader.jl")
    include("./entities.jl")
    using .Loader: load_data, read_config
    using .Entities: Agent, Space

    function main()
        spaces, agents = load_data(read_config("scenarios/eq_2.json"))
        synthetise_schedule(agents, spaces, order)
        # println(typeof(spaces), "\t", typeof(agents), "\t", typeof(locations), "\t", typeof(order))
    end
    function synthetise_schedule(agents::Vector{Agent}, spaces::Vector{Space})
        .
    end
    main()
end

Now, when I run the scheduler.jl file, I get the following error

LoadError: MethodError: no method matching synthetise_schedule(::Array{Main.Scheduler.Loader.Entities.Agent,1}, ::Array{Main.Scheduler.Loader.Entities.Space,1})

It looks like the REPL treat Main.Scheduler.Loader.Entities.* and Main.Scheduler.Entities.* as different types, although they eventually all refer to the same original types Entities.*.

Now, I am not sure if this behavior comes from the fact that I am missing a set of instructions within each module or if it is the expected behavior in Julia.

In any case, how can I make sure that my synthetise_schedule function accepts Main.Scheduler.Loader.Entities.* types as input?

This is expected, and it’s why you should ensure that each file is include()ed exactly once. In your case, it should be sufficient to do:

module Scheduler

include("loader.jl")  # Note: `./` is implied
using .Loader: load_data, read_config
using .Loader.Entities: Agent, Space
1 Like

It makes sense. But know, the final common types is Main.Scheduler.Loader.Entities.*, which works but is kind of misleading from a conceptual point of view since Main.Scheduler.Entities.* types also exist on their own.

The bottomline is that I always have to use the “longest” include as my final types (if that makes sense), which is not ideal.

Oh, sure–in that case you can do:

module Scheduler

include("entities.jl")
include("loader.jl")

as long as you also change loader.jl to look like:

module Loader

using ..Entities: Agent

That should allow you to have your Main.Scheduler.Entities types as desired.

2 Likes