# 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:** 1\
**Showing post:** 2

<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.

---

_[View the full topic](https://discourse.julialang.org/t/singleton-types-vs-instances-as-type-parameters/2802)._
