मुझे यह होमवर्क असाइनमेंट मिला है (होमवर्क टैग नहीं जोड़ा जा सका)। यह सिर्फ एक प्रशिक्षण समस्या है, हाथ में लेने का हिस्सा नहीं है। मैंने एक पुनरावर्ती फ़ंक्शन "eval" बनाया है जो पूर्णांक (+, -, *, /) पर सामान्य संचालन का मूल्यांकन करता है, अब तक, फ़ंक्शन जोड़, गुणा और घटाव का मूल्यांकन कर सकता है।
type expr =
| Const of int
| Add of expr * expr
| Mul of expr * expr
| Sub of expr * expr
let rec eval (n: expr): int =
match n with
| Const n -> n
| Add (a, b) -> eval a + eval b
| Mul (a, b) -> eval a * eval b
| Sub (a, b) -> eval a - eval b
यह फ़ंक्शन पूरी तरह से काम करता है। इसके बाद मुझे विभाजन के लिए अनुमति देने के लिए, expr प्रकार का विस्तार करना होगा:
| Div of expr * expr
इसके अलावा मुझे एक नया प्रकार बनाकर शून्य विभाजन के मामले से निपटने की जरूरत है:
('a, 'b) result
Eval का नया रिटर्न प्रकार कौन सा है (यह असाइनमेंट विवरण में है, इसलिए मुझे यह करना होगा)। यह मेरा प्रयास है:
type ('a, 'b) result =
| Ok of int
| Err of string
let rec eval (n: expr): ('a, 'b)result =
match n with
| Const n -> Ok(Const n)
| Add (a, b) -> Ok(eval a + eval b)
| Mul (a, b) -> OK(eval a * eval b)
| Sub (a, b) -> Ok(eval a - eval b)
| Div (_, Const 0) -> Err "zero division"
| Div (a, b) -> Ok(eval a / eval b)
लेकिन मुझे यह कहते हुए एक त्रुटि मिलती है कि ऑपरेटरों +, -, * और / को प्रकार ('ए,' बी) परिणाम के लिए परिभाषित नहीं किया गया है, जो समझ में आता है। तो मेरा सवाल यह है कि क्या किसी नए प्रकार के अन्य प्रकारों से प्राप्त करने का कोई तरीका है? मैं कुछ ऐसा टाइप नहीं कर सकता:
type ('a, 'b) result =
| int
| Err of string
वह बात क्यों नहीं है? क्या मुझे कुछ कीवर्ड निर्दिष्ट करने हैं, इसलिए यदि मैं एक नए प्रकार में int का उपयोग करता हूं, तो int से संबद्ध रहें? एफ # वही आउटपुट प्रकार चाहता है, इनपुट से कोई फर्क नहीं पड़ता, क्या इसके आसपास कोई रास्ता है? क्या मैं फ़ंक्शन को बता सकता हूं कि आउटपुट या तो एक पूर्णांक या एक स्ट्रिंग है, अगर मैंने नया प्रकार नहीं बनाया है?
2 जवाब
संक्षिप्त उत्तर है नहीं। जैसा आपने कहा था एफ # केवल एक रिटर्न प्रकार की अनुमति देता है।
इस मामले में आपके result
प्रकार के मानों के 2 संभावित सेट हैं, Ok
मान और Error
मान। आपके कोड को दोनों पॉज़िबिलिट्स पर विचार करने की आवश्यकता है, आप एक को अनदेखा नहीं कर सकते। याद रखें eval a
अब कोई int
नहीं लौटाता, अब यह एक result
लौटाता है, जिसके अंदर एक int
हो भी सकता है और नहीं भी।
आपके eval a
और eval b
के बाद लेकिन +
, -
, *
या /
को कॉल करने से पहले, आपको यह जांचना होगा कि दोनों में से कोई एक परिणाम है या नहीं Error
. यदि दोनों Ok
हैं, तभी आप ऑपरेटर को लागू कर सकते हैं। यदि उनमें से कोई एक Error
है, तो आपको त्रुटि वापस करनी होगी, है ना?
उदाहरण के लिए, (और int
निकालने के लिए) आप match
का उपयोग कर सकते हैं:
match eval a , eval b with
| Ok a', Ok b' -> Ok(a' + b')
| Error e , _
| _ , Error e -> Error e
याद रखें कि आपको ऊपर दिए गए निर्देशों को 4 बार कॉपी करने की आवश्यकता नहीं है। आप एक फ़ंक्शन बना सकते हैं और ऑपरेटर को पैरामीटर के रूप में पास कर सकते हैं इस सिंटैक्स का उपयोग करते हुए: (+)
, (-)
, (*)
, (/)
।
एक और युक्ति: आप केवल Const 0
से विभाजन के मामले पर विचार कर रहे हैं। यदि आप गणना किए गए 0
, उदाहरण के लिए 5/(1 - 1)
से विभाजित कर रहे हैं तो क्या होगा?
कार्यात्मक प्रोग्रामिंग में इससे निपटने का एक और तरीका है। अंत में आपको एक Bind
फ़ंक्शन (या Apply
) की आवश्यकता है। इसके बारे में जानने का एक अच्छा संसाधन यह साइट है: https://fsharpforfunandprofit.com/rop/
आप पूछ रहे हैं कि क्या एफ # आपको कुछ ऐसा करने की अनुमति देता है:
type Result = int | string
यह एक अनुचित अपेक्षा नहीं है, टाइपस्क्रिप्ट बिल्कुल यही अनुमति देता है। एफ # नहीं, आपने प्रत्येक मामले के लिए एक नया प्रकार परिभाषित किया है।
type Result = Ok of int | Err of string
यह इस मामले में थोड़ा परेशान करता है, दी गई है, लेकिन यह भेदभावपूर्ण यूनियनों को बनाने के लिए इसे और अधिक स्वाभाविक बनाता है - यूनियनों को किसी तरह से "भेदभाव" किया जाता है, यहां उनके प्रकार के नाम से। टाइपस्क्रिप्ट में, आपको प्रत्येक मामले में एक सामान्य संपत्ति जोड़नी होगी, जो कि थोड़ा अनाड़ी है।
मूलभूत अंतर यह है कि F# .NET टाइप सिस्टम पर निर्मित होता है जो नाममात्र का है, और टाइपस्क्रिप्ट एक स्ट्रक्चरल टाइप सिस्टम है। .NET उनके नामों से प्रकारों को अलग करता है, टाइपस्क्रिप्ट उनकी सामग्री द्वारा प्रकारों को अलग करता है। तो आप स्वयं को F# में कुछ और प्रकार के नाम बनाते हुए पाएंगे।
संबंधित सवाल
नए सवाल
function
एक फ़ंक्शन (इसे एक प्रक्रिया, विधि, सबरूटीन या रूटीन भी कहा जाता है) एक एकल, विशिष्ट कार्य को करने के उद्देश्य से कोड का एक हिस्सा है। इस टैग का उपयोग उन प्रश्नों के लिए करें जिनमें विशेष रूप से कार्य करना या कॉल करना शामिल है। किसी कार्य को करने के लिए फ़ंक्शन को लागू करने में मदद के लिए, इसके बजाय [एल्गोरिथ्म] या कार्य-विशिष्ट टैग का उपयोग करें।