Inability to pass function with type parameters as an argument

We have 2 functions

  1. identity just returns its first argument
  2. test accepts a Nat → Nat function and calls it

Why cannot we use identity as an argument for the test function?
I am getting “expression of type … cannot produce expected type” error.

2 Likes

I cant speak to the technical reason but you can get around it with another function
ignore test(func (n: Nat) = identity<Nat>(n));
https://m7sm4-2iaaa-aaaab-qabra-cai.ic0.app/?tag=1307026162

It is a good thing there is a way to get around it, yet still I hope we’d be able to do it the correct way one day

I think it works in the example you shared because we explicitly specify <Nat> parameter
On the other hand, if we don’t call the identity function (just pass it around, as in my example), there is no way to explicitly specify the parameter

@claudio What do you think about the error above? Are there any plans to support it in the future?

Do you mean you want to be able to write:

ignore test(identity<Nat>);

?

Hopefully, It works even without <Nat>. But identity<Nat> would be a good workaround

I sympathize with this and it is definitely what users expect from ML-like languages (SML, OCaml, F#, Haskell).

Unfortunately, it might actually be problematic for the subtyping we use in Motoko, i.e. it is possible it makes subtyping undecidable. Would need to look at the literature to be sure.

1 Like

It is strange that inline function works here even without specifying parameter type and return type
ignore test(func(n) = identity(n)); (modified @Gekctek’s suggestion)
but we still can not pass a function with type parameters directly

Type instantiation is part of function call syntax in Motoko, it does not exist as a stand-alone thing – dually, you cannot introduce generic parameters without function parameters, and there are no generic types independent from functions. It behaves similar to most conventional languages rather than ML-style ones in that regard.

There are a few technical reasons for this, which have to do with compilation, side effects, and the lack of partial application in Motoko. FWIW, I don’t think subtyping poses a problem here, it primarily comes down to a form of currying (with runtime type passing, it literally is), but Motoko does not support that either.

@ZhenyaUsenko, this is no different from regular parameters, where you cannot pass a two-argument function f as test(f(3)), but have to write test(func(n) = f(3, n)) instead.