How to comprehend Algorithm W in Hindley–Milner type system? - hindley-milner

I am studying the algorithm W. From my understand, algorithm W takes (Γ,expr) as input ,where Γ is the context, and expr is the expression. The output is a substitution σ. Then I can use the substitution σ to take another (Γ,expr) as σ(Γ,expr).
What confuses me is what to do next. Since expr can have cases as: variable, abstraction, application, condition, fix-point expression, and let expression.
What is the purpose of having different cases of expr? What should I do in the next step?

Algorithm W does not only return a substitution but also a type τ which is the type inferred from the expression that you fed in the algorithm from the beginning.
A substitution S is a map from a type variable α to a type τ and therefore a substitution does not rely on the type environment Γ as you have implied.
Each case is handled separately (e.g. application uses unification but the other that you have mentioned does not) and interconnected in a recursive manner. Here is the pseudocode for algorithm W for some expressions

Related

Modelica annotation derivative: noDerivative versus zeroDerivative

I have successfully used annotation(derivative) in Modelica functions. Now I have reached a point where I think I need to use zeroDerivative or noDerivative, but from the specification I just do not understand what is the difference, and when to use what.
https://specification.modelica.org/v3.4/Ch12.html#declaring-derivatives-of-functions
It seems zeroDerivative is for time-constant parameters??
Does somebody have a simple example?
Use zeroDerivative to refer to inputs that are non-varying, i.e. parameters or constant values.
Use noDerivative for signals that do not have a derivative value. For example if an input signal comes from an external function.
The important case for noDerivative is when the input is "redundant".
As an example consider the computation of density for some media in MSL:
The density computation is found in Modelica.Media.R134a.R134a_ph.density_ph (note this does not contain any derivative in itself):
algorithm
d := rho_props_ph(
p,
h,
derivsOf_ph(
p,
h,
getPhase_ph(p, h)));
where the top function called is:
function rho_props_ph
"Density as function of pressure and specific enthalpy"
extends Modelica.Icons.Function;
input SI.Pressure p "Pressure";
input SI.SpecificEnthalpy h "Specific enthalpy";
input Common.InverseDerivatives_rhoT derivs
"Record for the calculation of rho_ph_der";
output SI.Density d "Density";
algorithm
d := derivs.rho;
annotation (
derivative(noDerivative=derivs) = rho_ph_der ...);
end rho_props_ph;
So the derivs-argument is sort of redundant and is given by p and h; and we don't need to differentiate it again. If you send in a derivs-argument that isn't given in this way may give unpredictable result, but describing this in detail would be too complicated. (There was some idea of noDerivative=something - but even just specifying it turned out to be too complicated.)
For zeroDerivative the corresponding requirement is that the arguments have zero derivative; that is straightforward to verify and if non-zero we cannot use the specific derivative (it is possible to specify multiple derivatives and use another derivative one for that case).

Can all values of types with unit be created with unit?

In Functional Programming in Scala, when introducing the concept of the algebra of an API, they propose the following law
map(unit(x))(f) == unit(f(x))
for some value x and function f. So far unit has been a way to create a unit of parallelism Par[A], but I guess it doesn't have to be here. I anticipate it's the same unit as in monads. map is what you think it is.
They substitute the identity id for f
map(unit(x))(id) == unit(id(x))
map(unit(x))(id) == unit(x)
and finally substitute y for unit(x)
map(y)(id) == y
I don't get how they make this last step, unless all possible values of that type can be constructed by unit, which doesn't seem right since Par[A] is a type alias for a function, along some object-level functions, and I'd have thought it trivial to hand-craft some new Par[A] functions without unit. Given they're talking quite abstractly, my question is how this works generally, not just for their Par[A] type.
I have the same book here. If you take a look at the notes, the author says:
This is the same sort of substitution and simplification one might do when solving an algebraic equation.
Which, in terms of functional programming, means that mapping any value y over id should be equals to y. If we take the concept of referential transparency, which states that:
An expression is called referentially transparent if it can be replaced with its corresponding value without changing the program's behavior
y could represent any value, be it unit(x), x or any other value

Julia network expression Flux

Learning Julia metaprogramming to automatically construct ANN by expression. While everything works well for inference, a backward stage raises an error:
LoadError: Can't differentiate foreigncall expression
The next code shows where the problem appears. While eval(net(x)) works well, for some reason it throws an error at the gradient computation stage.
# define ANN by expression
net(x) = :($w2 * relu.($w1 * $x .+ $b1) .+ $b2)
# define loss and network evaluation
loss(x, y) = Flux.logitcrossentropy(eval(net(x)), y)
θ = Flux.Params([w1, b1, w2, b2])
# eval network and calculate gradients
gs = gradient(() -> loss(features, labels), θ) # where the problem appears
eval is a primitive which Flux can't differentiate. You'd rather use something like
net = :($w2 * relu.($w1 * x .+ $b1) .+ $b2)
#eval loss(x, y) = Flux.logitcrossentropy($net, y)
That builds the expression of loss and evaluates it once, instead of evaluating (and hence, compiling) the same piece of code every time the loss function is called.
But think twice before metaprogramming. Before resorting to eval, try to write a macro that generates your network and the loss function.
Of course this does not work if the goal is to plug together expression only available at runtime. Genetic programming, where you create a lot of random expressions at runtime, sounds like a justifiable exception. But even then, there maybe are alternatives, like using your own restricted representations (which, for example, you could first symbolically differnetiate, and then "compile" to an anonymous function).

assign derivative to function in Maple

I have a situation in Maple, where a large expression is calculated. In that expression a derivative appears, say $$\frac{\partial}{\partial x} f(x,t)$$. I know the function
$$\frac{\partial}{\partial x} f(x,t)$$
but I do not know the function f (and integrating makes the problem excessively difficult, it is not worth to explain the details). Here is my question: how can I get maple to replace $$\frac{\partial}{\partial x} f(x,t)$$ with my known function? A naive assignment such as
$$\frac{\partial}{\partial x} f(x,t):= expression$$
does not work.
It is using the subs command
https://www.maplesoft.com/support/help/Maple/view.aspx?path=subs
such as
subs( $$\frac{\partial}{\partial x} f(x,t)$$=known function, expression)

MATLAB symbolic expression

I have two expressions which are T="x +B " and K="Dt+Dc" and "T=K" . I want to write this expression for just D i.e. "D= (x+B)/t+c". Is there any function for this situation in MATLAB? My real expressions are not short which I gave as example.