Can a partial applicated operation be passed as an argument ?
Yes.
For example, let's say you want to pass an argument of type (Qubit => Unit)
(an operation applied to a single qubit, say, a gate), and you want to get it by using Ry
gate with a fixed rotation angle parameter. The signature of Ry
operation is operation Ry (theta : Double, qubit : Qubit) : Unit
, so its type is ((Double, Qubit) => Unit)
. If you use partial application to define a new operation
let RyHalfPi = Ry(PI() / 2.0, _);
the signature of the new operation will be (Qubit => Unit)
(since you already defined the first parameter), and it will behave as an operation that takes a single qubit parameter for all purposes, including passing it as an argument.
Can you first fill one argument, store it, fill another argument, store it, and then finally call the operation by filling the last argument ?
Yes, in exactly the same way as in the first case!
If, for example, you want to use R1Frac
gate with signature (Int, Int, Qubit) : Unit
, you can first fill in the numerator:
let R1Frac10 = R1Frac(10, _, _);
to get operation with signature (Int, Qubit) : Unit
, and then fill in the power to get a single-qubit gate:
for (power in 0 .. 1 << 10) {
let R1Frac10Power = R1Frac10 (power, _);
// ...
}
You can also fill in parameters out of order (not necessarily left to right like I did in the example), following the same principle: you'll get an operation which takes all leftover (unsupplied) arguments in the order in which they are left.
- You can check the testing harnesses of the Quantum Katas for more examples - they use partial application quite extensively to use unified testing harness for tasks with slightly different operation signatures.