Tür parametreleştirmeleri

Q# tür parametreli işlemleri ve işlevleri destekler. Q# standart kitaplıklar, işlevsel dillerden tanıdık Mapped ve Fold gibi işlevler de dahil olmak üzere birçok yararlı soyutlama sağlamak için türe parametrized çağrılabilen öğelerden yoğun bir şekilde yararlanmaktadır.

Tür parametreleştirmeleri kavramını motive etmek için, dizideki her değere belirli bir işlevi uygulayan ve hesaplanan değerlerle yeni bir dizi döndüren Mappedişlevinin örneğini düşünün. Bu işlev, giriş ve çıkış dizilerinin öğe türleri belirtilmeden mükemmel bir şekilde açıklanabilir. Tam türler işlevin Mappeduygulamasını değiştirmediğinden, bu uygulamayı rastgele öğe türleri için tanımlamanın mümkün olması gerekir; giriş ve çıkış dizisindeki öğelerin somut türleri göz önüne alındığında ilgili işlev uygulamasını döndüren fabrika veya şablonu tanımlamak istiyoruz. Bu not, tür parametreleri biçiminde resmileştirilir.

Concretization

Herhangi bir işlem veya işlev bildirimi, çağrılabilir giriş veya çıkışının veya her ikisinin türleri veya türlerin bir parçası olarak kullanılabilecek bir veya daha fazla tür parametresi belirtebilir. Özel durumlar, somut olması gereken ve tür parametreli yapılamayan giriş noktalarıdır. Tür parametre adları bir değer işareti (') ile başlar ve giriş ve çıkış türlerinde birden çok kez görünebilir. Çağrılabilen imzada aynı tür parametresine karşılık gelen tüm bağımsız değişkenler aynı türde olmalıdır.

Türe parametrized çağrılabilen bir değerin birleştirilmesi, yani bağımsız değişken olarak atanabilmesi veya geçirilebilmesi için gerekli tür bağımsız değişkenleriyle sağlanması gerekir; böylece tüm tür parametreleri somut türlerle değiştirilebilir. Yerleşik türlerden biriyse, struct türündeyse veya geçerli kapsam içinde somutsa, bir tür somut olarak kabul edilir. Aşağıdaki örnek, bir türün geçerli kapsam içinde somut olması için ne anlama geldiğini gösterir ve aşağıda daha ayrıntılı olarak açıklanmıştır:

    function Mapped<'T1, 'T2> (
        mapper : 'T1 -> 'T2,
        array : 'T1[]
    ) : 'T2[] {

        mutable mapped = new 'T2[Length(array)];
        for (i in IndexRange(array)) {
            mapped w/= i <- mapper(array[i]);
        }
        return mapped;
    }

    function AllCControlled<'T3> (
        ops : ('T3 => Unit)[]
    ) : ((Bool,'T3) => Unit)[] {

        return Mapped(CControlled<'T3>, ops); 
    }

İşlev CControlledMicrosoft.Quantum.Canon ad alanında tanımlanır. Bağımsız değişken olarak 'TIn => Unit türünde bir işlem op alır ve klasik bir bit (Booltüründe) true olarak ayarlanmışsa özgün işlemi uygulayan (Bool, 'TIn) => Unit türünde yeni bir işlem döndürür; Bu genellikle opklasik denetimli sürümü olarak adlandırılır.

İşlev Mapped bağımsız değişken olarak 'T1 rastgele bir öğe türü dizisi alır, verilen mapper işlevini her öğeye uygular ve eşlenen öğeleri içeren 'T2[] türünde yeni bir dizi döndürür. Microsoft.Quantum.Array ad alanında tanımlanır. Örneğin amacı doğrultusunda, her iki işlevdeki tür parametrelerine aynı adı vererek tartışmanın daha kafa karıştırıcı olmasını önlemek için tür parametreleri numaralandırılır. Bu gerekli değildir; farklı çağrılabilirler için tür parametreleri aynı ada sahip olabilir ve seçilen ad yalnızca bu çağrılabilir tanımı içinde görünür ve ilgili olur.

AllCControlled işlevi bir işlem dizisi alır ve bu işlemlerin klasik olarak denetlenen sürümlerini içeren yeni bir dizi döndürür. Mapped çağrısı, 'T3 => Unitiçin 'T1 tür parametresini ve (Bool,'T3) => Unit'T2 tür parametresini çözümler. Çözümleme türü bağımsız değişkenleri, derleyici tarafından verilen bağımsız değişkenin türüne göre çıkarılır. Bunların, çağrı ifadesinin bağımsız değişkeni tarafından tanımlanan örtük olduğunu söylüyoruz. Tür bağımsız değişkenleri, aynı satırdaki CControlled için yapıldığı gibi açıkça da belirtilebilir. Tür bağımsız değişkenleri çıkarılamadığında açık concretization CControlled<'T3> gereklidir.

'T3 türü, AllCControlledher çağırma için bilindiğinden, AllCControlledbağlamında somut bir değerdir. Bu, programın giriş noktası -tür-parametrized olamaz- bilindiği anda, AllCControlledher çağrı için somut tür 'T3 olduğu anlamına gelir, böylece ilgili tür çözümlemesi için uygun bir uygulama oluşturulabilir. Bir programın giriş noktası bilindikten sonra, tür parametrelerinin tüm kullanımları derleme zamanında ortadan kaldırılabilir. Bu işleme monomorfizasyonolarak adlandırıyoruz.

Bunun yalnızca çalışma zamanında değil, derleme zamanında yapılabilmesini sağlamak için bazı kısıtlamalar gerekir.

Kısıtlamalar

Aşağıdaki örneği göz önünde bulundurun:

    operation Foo<'TArg> (
        op : 'TArg => Unit,
        arg : 'TArg
    ) : Unit {

        let cbit = RandomInt(2) == 0;
        Foo(CControlled(op), (cbit, arg));        
    } 

Foo çağrılarının sonsuz döngüye neden olduğunu yoksayarak, çizim amacına hizmet eder. Foo, özgün işlem op geçirilen klasik denetimli sürümüyle ve özgün bağımsız değişkenine ek olarak rastgele klasik bit içeren bir tanımlama grubuyla kendisini çağırır.

Özyinelemedeki her yineleme için, sonraki çağrının tür parametresi 'TArg(Bool, 'TArg)olarak çözümlenir; burada 'TArg geçerli çağrının tür parametresidir. Somut olarak, FooH işlemi ve Qubittüründe bir bağımsız değişken arg ile çağrıldığı varsayın. Foo sonra kendisini (Bool, Qubit)bir tür bağımsız değişkeniyle çağırır ve ardından (Bool, (Bool, Qubit))tür bağımsız değişkeniyle Foo çağırır. Bu durumda Foo derleme zamanında tek biçimli hale getirilemez.

Çağrı grafında yalnızca tür parametrized çağrılabilen öğeler içeren döngüler için ek kısıtlamalar geçerlidir. Çağrılabilir her birinin döngüden geçirildikten sonra aynı tür bağımsız değişkenleri kümesiyle çağrılması gerekir.

Uyarı

Daha az kısıtlayıcı olabilir ve döngüdeki çağrılabilir her biri için, aşağıdaki işlev için olduğu gibi özgün tür bağımsız değişkenleri kümesiyle çağrıldıktan sonra sonlu bir döngü sayısı olmasını zorunlu kılabilir:

   function Bar<'T1,'T2,'T3>(a1:'T1, a2:'T2, a3:'T3) : Unit{
       Bar<'T2,'T3,'T1>(a2, a3, a1);
   }

Kolaylık olması için daha kısıtlayıcı bir gereksinim uygulanır. Herhangi bir tür parametresi olmadan en az bir somut çağrılabilir içeren döngüler için, bu tür çağrılabilirlerin söz konusu döngü içindeki tür parametrized çağrılabilirlerin her zaman sabit bir tür bağımsız değişkenleri kümesiyle çağrılmasını sağladığını unutmayın.