# Singleton types vs. instances as type parameters

**URL:** <https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802>\
**Category:** General Usage\
**Created:** [March 21, 2017, 6:28pm UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802 "2017-03-21T18:28:56Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 21, 2017, 6:28pm UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/1 "2017-03-21T18:28:56Z")

</div>

Let’s say I want to create a family of singleton types, and additional types that might use them as type parameters. The particular example I’m thinking of is a named `Variable` type, and a type to hold powers of that variable:

```julia
struct Variable{Name}
  Variable{N}() where {N} = new{typeassert(N, Symbol)}()
end

```

I have a choice here: I can either use the variable type as a parameter, or I can use its singleton instance. That is, I can do this:

```julia
struct Power{V <: Variable}
  exponent::Int
end

```

or this:

```julia
struct Power{V}
  exponent::Int 

  Power{V}(e::Int) where {V} = new{typeassert(V, Variable)}()
end

```

The first form seems cleaner and easier to write in this case. However, if I want to use a tuple of variables as parameters, I _must_ use instances rather than types:

```julia
julia> struct Monomial{Vars}
       exponents
       end

julia> Monomial{(Variable{:x}, Variable{:y})}
ERROR: TypeError: Type: in parameter, expected Type, got Tuple{DataType,DataType}

julia> Monomial{(Variable{:x}(), Variable{:y}())}
Monomial{(Variable{:x}(), Variable{:y}())}

```

so for consistency with other types that might need a tuple of parameters, using instances seems preferable. Or perhaps it would be better to do `Monomial{Tuple{Variable{:x}, Variable{:y}}}`?

My question is: are there other trade-offs that I haven’t brought up here?

For example, are there any efficiency differences between `Power{Variable{:x}}` and `Power{Variable{:x}()}`? Or have any of you tried structures like this, and did you form a clear preference? I imagine that the authors of packages like Unitful.jl have faced similar questions.

Thanks!

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 21, 2017, 6:54pm UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/2 "2017-03-21T18:54:12Z")

</div>

> [@rdeits](#):
>
> an either use the variable type as a parameter, or I can use its singleton instance

Oh yes, this question 🙂. Fond memories. In JuliaDiffEq, we had a similar problem: what should

```julia
solve(prob,alg)

```

dispatch on, the type of `alg` or its instance? We had a month where we:

1. Went with the type
2. Went to the instance
3. Went back to the type
4. Finally at the instance.

It has stayed with the instance ever sense. Example:

```julia
solve(prob,RK4())

```

The reason is because this is much more flexible. It took me awhile to get here though! Arguments are given here:

> <https://github.com/SciML/Sundials.jl/issues/97>
>
> Now that there is the common interface, more refined algorithm choices can occur… from in the same general \`solve\` command. Some different examples of things would be:
> 
> \- Changing solver option. Right now the recommended defaults are used (\`BDF\` with Newton, and \`Adams\` with Functional). There are many reasons to switch this around, for example @AlexanderKoshkarov ran into memory issues with the Newton solver, so the way around that was to use the functional iteration because that doesn't require the linear solver. Allowing for more algorithm choices will enable users to do this without having to dig into the codes.
> \- Exposing the linear solver interface. This portion will be more difficult. Right now the common interface exposes only the dense solver (like the simple interface). For example, in most cases people likely want to use the banded solver for discretized PDEs which will be faster and more memory efficient than the dense solver. However, this will also mean exposing the right options as keyword arguments and documenting them appropriately. This will be a bit more work.
> 
> To implement this, I'll be adding to the algorithm types using the parameters. The first change is pretty simple, and they algorithm types will be:
> 
> \- CVODE\_BDF{Method,LinearSolver} : This will do the BDF + the method and the linear solver. The recommended will be as the manual recommends: CVODE\_BDF{:Newton,:Dense}, and will leave the option for adding more linear solver methods to expose.
> \- CVODE\_Adams{Method,LinearSolver} : This will do Adams + the method and the linear solver. The recommended will be as the manual recommends: CVODE\_Adams{:Functional,:None}. Note that really no second argument is required when \`:Functional\` is chosen.
> 
> This will allow the different options to be exposed and will make the algorithms different at compile-time, keeping their runtime performance.

The general idea is that, if you’re using the instance, you have the full power of the constructor. It is strictly more powerful while the syntax isn’t much more. Some examples are:

1. Defaults in the constructor. You might create a whole family of related types for dispatch using a type parameter. I see `Variable{:x}`. What if you wanted a default variable? Using an instance, you can easily make a default constructor that throws `:x` in there. If you go with the type, you cannot do such defaults later.

2. If you want some kinds of relations between the types and values in the parameters, you can enforce that with a constructor.

3. You can add details (more parameters) without breaking code. If you suddenly need a second parameter, say some number which is normally 1 but 2 is some cool new feature, codes which use `Variable{:x}` will break when you go to `Variable{:x,1}`, but again a constructor can handle this by putting a default in there.

4. You never know if you’ll need fields! You have the option to use them in the future if you use instances, even if it’s just for storing some constants.

There’s probably a bit more too, but that’s the general idea. The flexibility is helpful in the long run.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 21, 2017, 7:05pm UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/3 "2017-03-21T19:05:01Z")

</div>

Thanks, @ChrisRackauckas that’s exactly the kind of information I was looking for! I’ve gone through that same set of permutations myself several times, but the point about handling defaults and additional type parameters makes a lot of sense, and it’s not something I’d considered before. Thank you!

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 21, 2017, 8:00pm UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/4 "2017-03-21T20:00:16Z")

</div>

In this discussion [How to make a vector of parametric composite types? - #11 by Olivier\_Merchiers](https://discourse.julialang.org/t/how-to-make-a-vector-of-parametric-composite-types/2439/11) it also appeared from benchmarks that empty instances were faster than using types.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [March 22, 2017, 12:20am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/5 "2017-03-22T00:20:17Z")

</div>

I remember reading somewhere or being told that it was recommended to use types, rather than instances, but since I don’t have a reference for that, consider it hearsay.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 22, 2017, 12:25am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/6 "2017-03-22T00:25:04Z")

</div>

You inadvertently were one that led me to realize that using the types directly was a bad idea 🙂

> <https://stackoverflow.com/questions/40687337/making-a-no-parameter-type-have-defaults>

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [March 22, 2017, 1:01am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/7 "2017-03-22T01:01:13Z")

</div>

Ha, apparently one is one’s own best teacher…!

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [March 22, 2017, 5:05am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/8 "2017-03-22T05:05:23Z")

</div>

The docs seem to imply this [http://docs.julialang.org/en/release-0.5/manual/types/#man-singleton-types](http://docs.julialang.org/en/release-0.5/manual/types/#man-singleton-types)  
" This is useful for writing methods (especially parametric ones) whose behavior depends on a type that is given as an explicit argument rather than implied by the type of one of its arguments."

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [March 22, 2017, 5:36am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/9 "2017-03-22T05:36:16Z")

</div>

I think that sentence just means that it’s useful for things like `parse(Int, "0")`.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 22, 2017, 6:05am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/10 "2017-03-22T06:05:48Z")

</div>

Thanks everyone! I ended up choosing the instances approach, and it’s going well so far.

Work is underway here: [https://github.com/rdeits/TypedPolynomials.jl/tree/abstract-vars](https://github.com/rdeits/TypedPolynomials.jl/tree/abstract-vars) (I’ll post this once it’s in a usable state).

---

<div class="post-metadata">

**Author:** ![andyferris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andyferris/32/235_2.png) [@andyferris](https://discourse.julialang.org/u/andyferris)\
**Post date:** [March 22, 2017, 7:20am UTC](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802/11 "2017-03-22T07:20:21Z")

</div>

This is a very interesting thread. I too have used both, oscillating between the two.

I believe the place where this advice was dispenced was begins in this point of this github thread: [https://github.com/JuliaLang/julia/pull/9452#issuecomment-68528662](https://github.com/JuliaLang/julia/pull/9452#issuecomment-68528662)

I have actually come full circle since then (at least once) - and now I believe instances are more powerful and flexible. for traits and singletons. In fact, that discussion seems to predate `@pure` - it might be worth reviewing `Val(x)::Val{x}` in this light (that’s easy syntax for both the caller and callee).

Thank you @rdeits for showing the `typeassert` trick - that’s _very_ neat, I usually do these type parameter assertions in a cluncky way.
