# Constructors with explicit and implicit types

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

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

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

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

and they work. But these fail.

``````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!

You need to define

``````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)
``````
1 Like

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

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

was same as

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

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

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

Also which order is preferred?

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

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!

2 Likes