你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

运算和函数

量子比特数据类型介绍中的详细阐述,量子计算以目标量子处理器原生支持的运算的副作用形式执行。 事实上,这些是 Q# 中的唯一副作用。 由于所有类型均不可变,因此没有任何副作用会影响 Q# 中显式表示的值。 因此,在输入相同的情况下,只要特定可调用对象的实现不直接或间接调用其中任何一个原生实现的运算,其执行就始终会生成相同的输出。

Q# 允许将这种纯粹的确定性计算显式拆分为函数。 由于原生支持的指令集不是固定的且不内置于语言本身,而是完全可配置的并表示为 Q# 库,因此,可要求函数只能调用其他函数且不能调用任何运算,来保证确定性。 此外,非确定性的原生指令(即,由于它们影响量子状态)将表示为运算。 有了这两个限制,只要知道函数的输入值,就可以对函数进行求值,并且原则上永不需要对同一输入进行多次求值。

因此,Q# 区分两种类型的可调用对象:运算和函数。 所有可调用对象将单个参数(可能是元组值参数)用作输入,并生成单个值(元组)作为输出。 在语法上,运算类型表示为 <TIn> => <TOut> is <Char>,其中的 <TIn> 将替换为参数类型,<TOut> 将替换为返回类型,<Char> 将替换为运算特征。 如果不需要指定特征,则语法将简化为 <TIn> => <TOut>。 类似地,函数类型表示为 <TIn> -> <TOut>

除了这种确定性保证之外,运算和函数之间几乎没有差别。 两者都是可以自由传递的第一类值;它们可以用作其他可调用对象的返回值或参数,如以下示例所示:

function Pow<'T>(op : 'T => Unit, pow : Int) : 'T => Unit {
    return PowImpl(op, pow, _);
}

这两者都可基于类型参数化定义进行实例化(例如上面的类型参数化函数 Pow),并且它们可部分应用,如示例中的 return 语句所示。

运算特征

除了有关输入和输出类型的信息之外,运算类型还包含有关运算特征的信息。 例如,此信息描述运算支持哪些仿函数。 此外,内部表示形式还包含编译器推理的优化相关信息。

运算的特征是一组预定义且内置的标签。 它们以作为类型签名一部分的特殊表达式的形式表示。 该表达式由一组预定义的标签组成,或者是通过支持的二元运算符组合的一系列特征表达式。

有两个预定义的集:AdjCtl

  • Adj 是包含单个标签的集,该标签表示运算可伴随 - 即,它支持 Adjoint 仿函数,并且可以“撤消”(即还原)应用的量子变换。
  • Ctl 是包含单个标签的集,该标签指示运算可控 - 即,它支持 Controlled 仿函数,并且可基于其他量子比特的状态为该运算的执行设置条件。

支持用作特征表达式的一部分的两个运算符是并集 + 和交集 *。 在 EBNF 中,

    predefined = "Adj" | "Ctl";
    characteristics = predefined 
        | "(", characteristics, ")" 
        | characteristics ("+"|"*") characteristics;

如预期的那样,* 的优先级高于 +,两者都是左关联的。 例如,单元运算的类型表示为 <TIn> => <TOut> is Adj + Ctl,其中的 <TIn> 应替换为运算参数的类型,<TOut> 应替换为返回值的类型。

注意

以这种形式指示运算特征可以获得两项主要优势:一方面,可以引入新的标签,而无需为所有标签组合使用成倍增加的语言关键字。 也许更重要的是,使用表达式指示运算特征还在将来支持对运算特征进行参数化。