# Dispatching on module to prove ownership in package extensions

**URL:** https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037
**Category:** General Usage
**Tags:** question, package-extensions
**Created:** [August 21, 2023, 3:54pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037 "2023-08-21T15:54:14Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [August 21, 2023, 3:54pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/1 "2023-08-21T15:54:14Z")

</div>

I was watching @kristoffer.carlsson’s JuliCon talk on [Package Extensions](https://www.youtube.com/watch?v=vG6ZLhe9Hns&t=23594s) and I was quite interested in the [discussion about “proving” dependencies](https://www.youtube.com/watch?v=vG6ZLhe9Hns&t=24717s) to ensure that a user _explicitly_ loads the package for which there is a package extension.

The code snippet given in the talk is

```julia
function solve_system(A, x; alg::Module)
    ext_hypre = Base.get_exension(@ __MODULE__ :HYPREExt)
    if ext_hypre !== nothing && alg == ext_hypre.HYPRE
        _solve_system(HYPRESolver(), A, x)
    elseif alg == ...
        # ...
    end
end

```

making users pass a module as `alg` to ensure that they’ve loaded the dependency explicitly.

I was wondering if there was a recommended pattern for generalizing this code to use multiple dispatch for choosing the solver. This would be to avoid the potentially long if-elseif-chain and to allow users to define their own optimization methods in their own (non-extension) modules.

The example snippet addresses the exact situation that I have in [QuantumControl.jl](https://github.com/JuliaQuantumControl/QuantumControl.jl#readme) (or actually, `QuantumControlBase.jl`) where currently, I’m dispatching on symbols for the optimization method, as

```julia
optimize(problem; method) = optimize(problem, method) # keyword arg (public API)
optimize(problem, method::Symbol) = optimize(problem, Val(method))

```

and then e.g. in [Krotov.jl](https://github.com/JuliaQuantumControl/Krotov.jl#readme), I have

```julia
optimize(problem, method::Val{:krotov}) = optimize_krotov(problem)

```

I might want to move that definition from `Krotov.jl` to an extension module of `QuantumControl.jl` so that users don’t necessarily have to install all the packages for the various methods to use `QuantumControl.jl` with just one method. At the same time, I’d like to keep the ability for someone to have their own method in a package I don’t know anything about, and extend `optimize` in a consistent fashion.

Unfortunately, I don’t think there’s any way to _directly_ dispatch on a module, since `typeof(SomeModule)` is `Module`. It would have been nicer if `typeof(SomeModule)` was a singleton sub-type of `Module` (just like `typeof(some_function)` is a subtype of `Function`), but without that, it seems to me the easiest way to implement it is to simply add

```julia
optimize(problem, method::Module) = optimize(problem, Val(nameof(method)))

```

That is, dispatch on the name of the module as a symbol.

Are there any better way to more directly dispatch on a Module?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [August 22, 2023, 6:42am UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/2 "2023-08-22T06:42:21Z")

</div>

> [@goerz](#):
>
> Unfortunately, I don’t think there’s any way to _directly_ dispatch on a module, since `typeof(SomeModule)` is `Module`

In Julia 1.10+ you can have a module as a type parameter and do something like (using the same example as in the talk):

```julia
julia> module HYPRE end;

julia> module Pardiso end;

julia> struct Algorithm{T} end

julia> f(::Algorithm{HYPRE}) = "HYPRE"
f (generic function with 1 method)

julia> f(::Algorithm{Pardiso}) = "Pardiso"
f (generic function with 2 methods)

julia> f(Algorithm{HYPRE}())
"HYPRE"

julia> f(Algorithm{Pardiso}())
"Pardiso"

```

That might be one way to use dispatch for it.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [August 22, 2023, 9:32am UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/3 "2023-08-22T09:32:57Z")

</div>

Will it also be possible to dispatch by the module itself, as in `f(::typeof(HYPRE)) = ... `?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [August 22, 2023, 3:43pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/4 "2023-08-22T15:43:22Z")

</div>

I don’t think so, same way you cannot dispatch on `f(::typeof(:symbol))`.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [August 22, 2023, 3:56pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/5 "2023-08-22T15:56:51Z")

</div>

Dispatch is possible by structs, types, functions — why not for modules?..  
Well, at least `Val(MyModule)` will work, right?

---

<div class="post-metadata">

### Author: ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)
#### Post date: [August 22, 2023, 4:25pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/6 "2023-08-22T16:25:44Z")

</div>

As of ~~1.9~~ 1.10, I believe so. [Allow Module as type parameters by Keno · Pull Request #47749 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/47749) is the PR which enabled this.

Edit: missed Kristoffer’s comment above.

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [August 22, 2023, 5:23pm UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/7 "2023-08-22T17:23:46Z")

</div>

> > Well, at least `Val(MyModule)` will work, right?
> 
> As of 1.9, I believe so. [Allow Module as type parameters by Keno · Pull Request #47749 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/47749) is the PR which enabled this.

Unfortunately, I don’t think that made it into 1.9. In fact, I’m pretty sure that PR is exactly what enables [“In Julia 1.10+ you can have a module as a type parameter”](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/2). Definitely something to look forward to in the next version!

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [August 23, 2023, 1:09am UTC](https://discourse.julialang.org/t/dispatching-on-module-to-prove-ownership-in-package-extensions/103037/8 "2023-08-23T01:09:17Z")

</div>

> [@aplavin](#):
>
> Dispatch is possible by structs, types, functions — why not for modules?..

Well, not functions, just the type of functions. Neither functions nor modules are types. You can define a method with the signature `f(::typeof(:symbol))` or `f(::typeof(HYPRE))`, that just evaluates to `f(::Symbol)` and `f(::Module)`. If you mean something like `::Type{T}` to narrow down a type’s type, that’s just type parameters.
