अपने विशिष्ट प्रश्न के लिए कैसे अपने isValidUnitValue
समारोह लिखने के लिए, जवाब है:
let inline isValidUnitValue myUnit = myUnit > LanguagePrimitives.GenericZero
तो तुम एक साथ भेदभाव संघ परिभाषित करने की जरूरत नहीं है।
मूल प्रश्न के संबंध में क्या एक ऐसा फ़ंक्शन परिभाषित करना संभव है जो डेटा प्रकार से अधिक सामान्य और dropUnit
जैसे माप की इकाई है, तो संक्षिप्त उत्तर नहीं है। यदि ऐसा फ़ंक्शन मौजूद है तो इसमें 'a<'b> -> 'a
जैसे हस्ताक्षर होंगे और इसका प्रतिनिधित्व करने के लिए प्रकार प्रणाली को उच्च प्रकार लागू करना चाहिए।
लेकिन वहाँ अधिभार और इनलाइन उपयोग करने चाल हैं:
1) भार के उपयोग (एक ला सी #)
type UnitDropper =
static member drop (x:sbyte<_> ) = sbyte x
static member drop (x:int16<_> ) = int16 x
static member drop (x:int<_> ) = int x
static member drop (x:int64<_> ) = int64 x
static member drop (x:decimal<_>) = decimal x
static member drop (x:float32<_>) = float32 x
static member drop (x:float<_> ) = float x
[<Measure>] type m
let x = UnitDropper.drop 2<m> + 3
लेकिन यह वास्तव में एक सामान्य समारोह नहीं है, आप कुछ सामान्य पर नहीं लिख सकते हैं इसके ऊपर
> let inline dropUnitAndAdd3 x = UnitDropper.drop x + 3 ;;
-> error FS0041: A unique overload for method 'drop' could not be determined ...
2) इनलाइन का उपयोग करना, एक आम चाल पुन: लिखने जाता है:
let inline retype (x:'a) : 'b = (# "" x : 'b #)
[<Measure>] type m
let x = retype 2<m> + 3
let inline dropUnitAndAdd3 x = retype x + 3
समस्या यह है कि retype
बहुत सामान्य है, यह आप लिखते हैं की अनुमति देगा:
let y = retype 2.0<m> + 3
जो संकलित करता है लेकिन रन-टाइम पर विफल हो जाएगा।
3) दोनों भार के और इनलाइन का उपयोग करना: इस चाल उपयोग के द्वारा दोनों मुद्दों एक मध्यवर्ती प्रकार के माध्यम से अधिक भार का समाधान होगा, इस तरह से आप प्राप्त दोनों संकलन समय चेक और आप सामान्य कार्यों को परिभाषित करने में सक्षम होंगे :
type DropUnit = DropUnit with
static member ($) (DropUnit, x:sbyte<_> ) = sbyte x
static member ($) (DropUnit, x:int16<_> ) = int16 x
static member ($) (DropUnit, x:int<_> ) = int x
static member ($) (DropUnit, x:int64<_> ) = int64 x
static member ($) (DropUnit, x:decimal<_>) = decimal x
static member ($) (DropUnit, x:float32<_>) = float32 x
static member ($) (DropUnit, x:float<_> ) = float x
let inline dropUnit x = DropUnit $ x
[<Measure>] type m
let x = dropUnit 2<m> + 3
let inline dropUnitAndAdd3 x = dropUnit x + 3
let y = dropUnit 2.0<m> + 3 //fails at compile-time
अंतिम पंक्ति में आप एक संकलन समय त्रुटि मिलेगी: FS0001: The type 'int' does not match the type 'float'
इस दृष्टिकोण का एक और लाभ यह है कि आप एक स्थिर मुझे परिभाषित करते हुए नए प्रकार के साथ बाद में इसे विस्तार कर सकते हैं है आपकी प्रकार की परिभाषा में mber ($) इस तरह:
type MyNumericType<[<Measure 'U>]> =
...
static member dropUoM (x:MyNumericType<_>) : MyNumericType = ...
static member ($) (DropUnit, x:MyNumericType<_>) = MyNumericType.dropUoM(x)
एक अन्य विकल्प नकली इंटरफ़ेस में इनलाइन फ़ंक्शन का उपयोग करना है। –