تعميم تلقائي (F#)
يستخدم F# استنتاج النوع لتقييم أنواع الدالات والتعبيرات. This موضوع describes how F# automatically generalizes the الوسيطات و أنواع of دالات so that they work مع multiple أنواع when this هو possible.
تعميم تلقائي
The F# compiler, when it performs نوع inference تشغيل a دالة, determines whether a given معلمة can be generic. The compiler examines each معلمة و determines whether the دالة has a تبعية تشغيل the specific نوع of that معلمة. If it does not, the نوع هو inferred إلى be generic.
The following تعليمات برمجية مثال illustrates a دالة that the compiler infers إلى be generic.
let max a b = if a > b then a else b
The نوع هو inferred إلى be 'a -> 'a -> 'a.
The type indicates that this هو a دالة that takes الثاني الوسيطات of the same نوع غير معروف و إرجاع a القيمة of that same type. واحد of the reasons that the السابق دالة can be generic هو that the greater-than عامل (>) هو itself generic. The greater-than عامل has the توقيع 'a -> 'a -> bool. Not الجميع عوامل تشغيل are generic, و if the تعليمات برمجية في a دالة uses a معلمة نوع together مع a non-generic دالة أو عامل, that معلمة نوع cannot be generalized.
Because max هو generic, it can be used مع أنواع such كـ int, float, و so تشغيل, كـ shown في the following أمثلة.
let biggestFloat = max 2.0 3.0
let biggestInt = max 2 3
However, the الثاني الوسيطات must be of the same نوع. The توقيع هو 'a -> 'a -> 'a, not 'a -> 'b -> 'a. Therefore, the following تعليمات برمجية produces an خطأ because the أنواع do not مطابقة.
// Error: type mismatch.
let biggestIntFloat = max 2.0 3
The max دالة also works مع أي نوع that supports the greater-than عامل. Therefore, you could also استخدم it تشغيل a سلسلة, كـ shown في the following تعليمات برمجية.
let testString = max "cab" "cat"
القيمة Restriction
المحول البرمجي يقوم بتعميم تلقائي فقط تشغيل ملفات تعريف دالة الكاملة التي تحتوي تشغيل صريح الوسيطات، وتشغيل قيم التغير بسيطة.
Th هو يعني المحول البرمجي هو sues خطأ عند محاولة ترجمة تعليمات برمجية التي هو مقيدة غير كاف ليكون نوع معين، ولكن هو أيضا غير عام. تشير رسالة الخطأ هذه المشكلة إلى هذا التقييد تشغيل تعميم auإلىmatic القيم ك قيمة قيد .
بشكل عام، يحدث خطأ قيد القيمة عندما تريد بناء أن يكون عاماً ولكن المحول البرمجي يحتوي على معلومات غير كافية عام عليه، أو عندما بدون قصد حذفت كافية نوع المعلومات في بناء nongeneric. حل الخطأ تقييد القيمة هو لتوفير معلومات أكثر واضحة لتقييد نوع المشكلة الاستخراج، بشكل كامل بإحدى الطرق التالية:
تقييد نوع إلى أن nongeneric بواسطة إضافة تعليق توضيحي نوع صريح إلى معلمة أو قيمة.
إذا كانت المشكلة هو استخدام بناء nongeneralizable لتعريف دالة عامة، مثل إنشاء دالة أو وسيطات الدالة curried incompletely المطبقة، حاول إعادة كتابة الدالة بتعريف دالة عادية.
إذا كانت المشكلة هو تعبير الذي هو معقد جداً أن generalized، به إلى دالة بإضافة معلمة إضافية، غير المستخدمة.
إضافة عام واضح معلمات نوع. نادراً ما يتم استخدام هذا الخيار.
توضح الأمثلة تعليمات برمجية التالية كل من هذه السيناريوهات.
الحالة 1: تعبير معقد جداً. في ترتيب هو سبيل المثال، lهوt sqrListهو تهدف إلى أن lهوt من الإعداد الصحيحة، ولكن هو لم يتم تعريف البسيطة القيمة التغير.
let sqrList = [ for i in 1..10 -> i*i ]
// Adding a type annotation fixes the problem:
let sqrList : int list = [ for i in 1..10 -> i*i ]
الحالة 2: استخدام بناء nongeneralizable لتعريف دالة عامة. في ترتيب هو سبيل المثال، بناء هو nongeneralizable لأن فإنه يتضمن تطبيق الجزئي وسيطات دالة.
let maxhash = max hash
// The following is acceptable because the argument for maxhash is explicit:
let maxhash obj = max hash obj
الحالة 3: إضافة معلمة إضافية، غير المستخدمة. Because this تعبير ليس simple enough for generalization, the compiler issues the القيمة restriction خطأ.
let emptyList10 = Array.create 10 []
// Adding an extra (unused) parameter makes it a function, which is generalizable.
let emptyList10 () = Array.create 10 []
الحالة 4: إضافة نوع معلمات.
let emptyset = Set.empty
// Adding a type parameter and type annotation lets you write a generic value.
let emptyset<'a> : Set<'a> = Set.empty