किसी न किसी अवलोकन
कार्यात्मक प्रोग्रामिंग में, एक फ़नकार अनिवार्य रूप से नए प्रकारों के चर के बीच के कार्यों के लिए साधारण एकरी फ़ंक्शंस (यानी एक तर्क वाले) उठाने का एक निर्माण है । सादे वस्तुओं के बीच सरल कार्यों को लिखना और बनाए रखना बहुत आसान है और उन्हें उठाने के लिए फंक्शनलर्स का उपयोग करें, फिर जटिल कंटेनर ऑब्जेक्ट्स के बीच फ़ंक्शन को मैन्युअल रूप से लिखना। आगे लाभ केवल एक बार सादे कार्यों को लिखने और फिर उन्हें अलग-अलग फ़ंक्शनलर्स के माध्यम से उपयोग करना है।
फ़ंक्शंस के उदाहरणों में सरणियाँ, "हो सकता है" और "या तो" फ़ंक्शनलर्स, फ़्यूचर्स (देखें उदाहरण https://github.com/Avaq/Fluture ), और कई अन्य शामिल हैं।
चित्रण
पहले और अंतिम नामों से पूर्ण व्यक्ति के नाम का निर्माण करने वाले फ़ंक्शन पर विचार करें। हम इसे fullName(firstName, lastName)
दो तर्कों के कार्य के रूप में परिभाषित कर सकते हैं , जो कि हालांकि उन तर्कों के लिए उपयुक्त नहीं होगा जो केवल एक तर्कों के कार्यों से निपटते हैं। उपाय करने के लिए, हम सभी तर्कों को एक ही वस्तु में एकत्रित करते name
हैं, जो अब फ़ंक्शन का एकल तर्क बन जाता है:
// In JavaScript notation
fullName = name => name.firstName + ' ' + name.lastName
अब अगर किसी सरणी में हमारे पास कई लोग हैं तो क्या होगा? मैन्युअल रूप से सूची पर जाने के बजाय, हम कोड की छोटी एकल पंक्ति के साथ सरणियों के लिए प्रदान की गई विधि के fullName
माध्यम से अपने फ़ंक्शन का पुनः उपयोग कर सकते हैं map
:
fullNameList = nameList => nameList.map(fullName)
और इसका उपयोग करें
nameList = [
{firstName: 'Steve', lastName: 'Jobs'},
{firstName: 'Bill', lastName: 'Gates'}
]
fullNames = fullNameList(nameList)
// => ['Steve Jobs', 'Bill Gates']
यह काम करेगा, जब भी हमारी हर प्रविष्टि nameList
एक वस्तु firstName
और lastName
गुण प्रदान करती है । लेकिन क्या होगा अगर कुछ वस्तुएं (या यहां तक कि सभी वस्तुएं नहीं हैं)? त्रुटियों से बचने के लिए और कोड को सुरक्षित बनाने के लिए, हम अपनी वस्तुओं को Maybe
टाइप में लपेट सकते हैं (जैसे उदाहरण https://sanctuary.js.org/#maybe-type ):
// function to test name for validity
isValidName = name =>
(typeof name === 'object')
&& (typeof name.firstName === 'string')
&& (typeof name.lastName === 'string')
// wrap into the Maybe type
maybeName = name =>
isValidName(name) ? Just(name) : Nothing()
जहां Just(name)
एक कंटेनर केवल वैध नाम है और Nothing()
वह विशेष मूल्य है जो हर चीज के लिए उपयोग होता है। अब हमारे तर्कों की वैधता की जांच करने के लिए (या भूल) के बजाय, हम fullName
कोड के एक और एकल पंक्ति के साथ हमारे मूल कार्य को पुन: उपयोग (लिफ्ट) कर सकते हैं , map
विधि के आधार पर , इस बार शायद प्रकार के लिए प्रदान किया गया है:
// Maybe Object -> Maybe String
maybeFullName = maybeName => maybeName.map(fullName)
और इसका उपयोग करें
justSteve = maybeName(
{firstName: 'Steve', lastName: 'Jobs'}
) // => Just({firstName: 'Steve', lastName: 'Jobs'})
notSteve = maybeName(
{lastName: 'SomeJobs'}
) // => Nothing()
steveFN = maybeFullName(justSteve)
// => Just('Steve Jobs')
notSteveFN = maybeFullName(notSteve)
// => Nothing()
श्रेणी का सिद्धांत
श्रेणी थ्योरी में एक फ़नकार दो श्रेणियों के बीच एक मानचित्र है जो उनके आकारिकी की संरचना का सम्मान करता है। एक में कंप्यूटर भाषा , ब्याज की मुख्य श्रेणी जिसका है वस्तुओं रहे हैं प्रकार (मूल्यों के कुछ सेट), और उसका morphisms हैं कार्यों एक प्रकार से अन्य प्रकार के ।f:a->b
a
b
उदाहरण के लिए, प्रकार, संख्या प्रकार a
होने के लिए ले लो , और इसकी लंबाई में एक स्ट्रिंग मैपिंग फ़ंक्शन है:String
b
f
// f :: String -> Number
f = str => str.length
यहाँ a = String
सभी स्ट्रिंग्स b = Number
के सेट और सभी नंबरों के सेट का प्रतिनिधित्व करता है । इस संदर्भ में, दोनों a
और b
में वस्तुओं का प्रतिनिधित्व सेट श्रेणी (जो बारीकी अंतर अनावश्यक यहाँ होने के साथ प्रकार की श्रेणी से संबंधित है,)। सेट श्रेणी में, दो सेटों के बीच आकारिकी पहले सेट से दूसरे में ठीक सभी कार्य हैं। तो f
यहाँ हमारी लंबाई कार्य संख्याओं के समूह में तार के सेट से एक आकृतिवाद है।
जैसा कि हम केवल निर्धारित श्रेणी पर विचार करते हैं, उसमें से प्रासंगिक फ़नवेक्टर , ऑब्जेक्ट्स को ऑब्जेक्ट्स और मॉर्फिज़्म को मॉर्फिज़्म में भेजने वाले मैप हैं, जो कुछ बीजीय कानूनों को संतुष्ट करते हैं।
उदाहरण: Array
Array
कई चीजों का मतलब हो सकता है, लेकिन केवल एक चीज एक फ़नकार है - प्रकार का निर्माण, एक प्रकार का मैपिंग जो सभी a
प्रकार [a]
के सरणियों के प्रकार में होता है a
। उदाहरण के लिए, Array
फ़नकार प्रकार String
में टाइप करता है [String]
(मनमानी लंबाई के तार के सभी सरणियों का सेट), और Number
इसी प्रकार में टाइप करें [Number]
(संख्याओं के सभी सरणियों का सेट)।
यह महत्वपूर्ण है कि फ़नकार के नक्शे को भ्रमित न करें
Array :: a => [a]
एक रूपवाद के साथ a -> [a]
। फ़नकार बस एक a
प्रकार की [a]
चीज़ को दूसरी चीज़ के रूप में टाइप करता है। प्रत्येक प्रकार वास्तव में तत्वों का एक सेट है, यहाँ कोई प्रासंगिकता नहीं है। इसके विपरीत, एक आकारिकी उन सेटों के बीच एक वास्तविक कार्य है। उदाहरण के लिए, एक प्राकृतिक रूपवाद (कार्य) है
pure :: a -> [a]
pure = x => [x]
जो एकल प्रविष्टि के रूप में उस मान के साथ 1-तत्व सरणी में मान भेजता है। वह फ़ंक्शन फ़नकार का हिस्सा नहीं है Array
! इस फ़नकार के दृष्टिकोण से, pure
किसी भी अन्य की तरह केवल एक फ़ंक्शन है, कुछ विशेष नहीं।
दूसरी ओर, Array
फ़नकार का अपना दूसरा भाग है - मोर्फिज़्म भाग। एक आकृतिवाद f :: a -> b
में कौन सा आकार एक रूपवाद देता है [f] :: [a] -> [b]
:
// a -> [a]
Array.map(f) = arr => arr.map(f)
यहाँ arr
प्रकार के मानों के साथ मनमानी लंबाई की कोई भी सरणी है a
, और प्रकार arr.map(f)
के मानों के साथ समान लंबाई की सरणी है b
, जिनकी प्रविष्टियाँ प्रविष्टियों के प्रविष्टियों पर लागू f
होती हैं arr
। इसे एक मज़ेदार बनाने के लिए, पहचान और रचनाओं से रचनाओं की पहचान मानचित्रण के गणितीय कानूनों को पकड़ना चाहिए, जो इस Array
उदाहरण में जांचना आसान है ।