# Constructors with explicit and implicit types

**URL:** <https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467>\
**Category:** General Usage\
**Created:** [August 14, 2018, 9:08pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467 "2018-08-14T21:08:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rakeshvar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rakeshvar/32/3613_2.png) [@rakeshvar](https://discourse.julialang.org/u/rakeshvar)\
**Post date:** [August 14, 2018, 9:08pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467/1 "2018-08-14T21:08:38Z")

</div>

I am implementing functor types. A simple example is the absolute value functor. (There is a scaling just to make the problem worthwhile.)

```julia
abstract type AbFun{F<:Real} end

struct Magnitude{F} <: AbFun{F}
    scale::F
end
Magnitude() = Magnitude(1.)
(self::Magnitude{F})(x::F) where F = abs(self.scale*x)

```

Now I have a function which has a fixed paramter `L`.

```julia
struct Huber{L, F} <: AbFun{F}
    scale::F
end
Huber() = Huber{1., typeof(1.)}(1.)

function (self::Huber{L, F})(x::F) where {L, F}
    sx = abs(self.scale*x)
    sx<1/L ? L*sx*sx/2 : sx-.5/L
end

```

Now I initialize

```julia
m1 = Magnitude()
m2 = Magnitude(2.)
h0 = Huber()
h2 = Huber{2., typeof(2.)}(2.)

```

and they work. But these fail.

```julia
Huber{2.}() # Want L = 2., scale = 1. (default)
Huber(2.) # Want L = 1. (default), scale = 2.
Huber{2.}(3.) # Want L = 2., scale = 3. *NEED THIS TO WORK*

```

Thanks!

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [August 14, 2018, 9:33pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467/2 "2018-08-14T21:33:24Z")

</div>

You need to define

```julia
Huber{L}(x::F) where {L,F} = Huber{L,F}(x)
Huber{L}() where L= Huber{L}(1.)
Huber(x::F) where F = Huber{1.}(x)

```

---

<div class="post-metadata">

**Author:** ![rakeshvar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rakeshvar/32/3613_2.png) [@rakeshvar](https://discourse.julialang.org/u/rakeshvar)\
**Post date:** [August 14, 2018, 9:54pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467/3 "2018-08-14T21:54:29Z")

</div>

Hmm… I almost thought it was that, but I guess I was confused because in previous versions …

```julia
unity{T}(x::T) = one(T)

```

was same as

```julia
unity(x::T) where T = one(T)

```

Here we seem to have both notations in one! as…

```julia
unity{T}(x::T) where T = ...

```

---

<div class="post-metadata">

**Author:** ![rakeshvar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rakeshvar/32/3613_2.png) [@rakeshvar](https://discourse.julialang.org/u/rakeshvar)\
**Post date:** [August 14, 2018, 9:56pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467/4 "2018-08-14T21:56:31Z")

</div>

Also which order is preferred?

```julia
struct Huber{L, F} <: AbFun{F} ... end
# or
struct Huber{F, L} <: Abfun{F} ... end

```

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [August 14, 2018, 10:04pm UTC](https://discourse.julialang.org/t/constructors-with-explicit-and-implicit-types/13467/5 "2018-08-14T22:04:27Z")

</div>

I think the `where` notation was introduced precisely to avoid that confusion.  
Note that `unity` is a function, not a type.  
They changed this syntax `unit{T}(x::T) = one(T)` to `unit(x::T) where T = one(T)` so that when you see something like `something{T}(x::T)...` you can be sure that that is a constructor to a type `something` with parametric type `T`, not a function with type signature.

* * *

Ps: When you define `Huber{L,F}(x::F) = ...` you are defining a type constructor, not a function!
