मुझे अभी नहीं पता कि वे किस समस्या का समाधान करते हैं।
मुझे अभी नहीं पता कि वे किस समस्या का समाधान करते हैं।
जवाबों:
भिक्षु न तो अच्छे होते हैं और न ही बुरे। वे बस हैं। वे उपकरण हैं जिनका उपयोग प्रोग्रामिंग भाषाओं के कई अन्य निर्माणों की तरह समस्याओं को हल करने के लिए किया जाता है। उनमें से एक बहुत ही महत्वपूर्ण अनुप्रयोग विशुद्ध रूप से कार्यात्मक भाषा में काम करने वाले प्रोग्रामर के लिए जीवन को आसान बनाना है। लेकिन वे गैर-कार्यात्मक भाषाओं में उपयोगी हैं; यह सिर्फ इतना है कि लोग शायद ही कभी महसूस करते हैं कि वे एक मोनाड का उपयोग कर रहे हैं।
मोनाड क्या है? मोनाड के बारे में सोचने का सबसे अच्छा तरीका एक डिज़ाइन पैटर्न है। आई / ओ के मामले में, आप शायद इसे महिमामंडित पाइपलाइन से थोड़ा अधिक होने के बारे में सोच सकते हैं जहां वैश्विक राज्य वह है जो चरणों के बीच से गुजर रहा है।
उदाहरण के लिए, आप जो कोड लिख रहे हैं, उसे ले लें:
do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Nice to meet you, " ++ name ++ "!")
आँख मिलने से यहाँ बहुत कुछ हो रहा है। उदाहरण के लिए, आप देखेंगे कि putStrLn
निम्नलिखित हस्ताक्षर हैं putStrLn :: String -> IO ()
:। ऐसा क्यों है?
इसके बारे में इस तरह से सोचें: चलो बहाना करते हैं (सादगी के लिए) कि stdout और stdin केवल फाइलें हैं जिन्हें हम पढ़ और लिख सकते हैं। एक अनिवार्य भाषा में, यह कोई समस्या नहीं है। लेकिन एक कार्यात्मक भाषा में, आप वैश्विक स्थिति को बदल नहीं सकते हैं। एक फ़ंक्शन केवल एक ऐसी चीज़ है जो एक मान (या मान) लेता है और एक मान (या मान) देता है। इसके आस-पास का एक तरीका यह है कि वैश्विक राज्य का उपयोग उस मान के रूप में किया जाए जो प्रत्येक फ़ंक्शन में और उसके बाहर हो रहा है। तो आप इस तरह से कोड की पहली पंक्ति का अनुवाद कर सकते हैं:
global_state <- (\(stdin, stdout) -> (stdin, stdout ++ "What is your name?")) global_state
... और संकलक कुछ भी छापना जानता है जो कि दूसरे तत्व में जोड़ा जाता है global_state
। अब मैं आपके बारे में नहीं जानता, लेकिन मुझे इस तरह से प्रोग्राम करने से नफरत होगी। जिस तरह से इसे आसान बनाया गया था, वह मोनाड्स का उपयोग करने के लिए था। एक मोनाड में, आप एक मान पास करते हैं जो एक क्रिया से दूसरे में किसी प्रकार की स्थिति का प्रतिनिधित्व करता है। इसके कारण putStrLn
वापसी का प्रकार है IO ()
: यह नई वैश्विक स्थिति लौटा रहा है।
तो आप क्यों परवाह करते हैं? खैर, अनिवार्य कार्यक्रम पर कार्यात्मक प्रोग्रामिंग के फायदों को कई जगहों पर मौत के लिए बहस किया गया है, इसलिए मैं सामान्य रूप से उस प्रश्न का उत्तर नहीं देने जा रहा हूं (लेकिन यदि आप कार्यात्मक प्रोग्रामिंग के मामले को सुनना चाहते हैं तो इस पेपर को देखें )। इस विशिष्ट मामले के लिए, यह मदद कर सकता है यदि आप समझ गए कि हास्केल क्या पूरा करने की कोशिश कर रहा है।
बहुत सारे प्रोग्रामर को लगता है कि हास्केल उन्हें अनिवार्य कोड लिखने या साइड इफेक्ट्स का उपयोग करने से रोकने की कोशिश करता है। यह बिल्कुल सच नहीं है। इसके बारे में इस तरह से सोचें: एक अनिवार्य भाषा वह है जो डिफ़ॉल्ट रूप से साइड इफेक्ट्स की अनुमति देती है, लेकिन यदि आप वास्तव में चाहते हैं (तो कुछ अंतर्विरोधों से निपटने के लिए तैयार हैं) आपको कार्यात्मक कोड लिखने की अनुमति देता है। हास्केल पूरी तरह से डिफ़ॉल्ट रूप से कार्यात्मक है, लेकिन यदि आप वास्तव में चाहते हैं (जो आप करते हैं यदि आपका कार्यक्रम उपयोगी होना है) तो आपको अनिवार्य कोड लिखने की अनुमति देता है। मुद्दा यह है कि साइड इफेक्ट वाले कोड को लिखना मुश्किल नहीं है। यह सुनिश्चित करना है कि आपको साइड इफेक्ट्स होने के बारे में स्पष्ट है (इस सिस्टम को लागू करने के प्रकार के साथ)।
goto
कागज में थोड़ी देर के बाद (संरचित प्रोग्रामिंग के लिए एक तर्क के रूप में) के उन्मूलन के बारे में एक ही बात कहता है , इस तरह के तर्कों को "फलहीन।" और फिर भी हम में से कोई भी गुप्त रूप से goto
वापसी की कामना नहीं करता है । यह केवल इतना है कि आप यह तर्क नहीं दे सकते कि goto
बड़े पैमाने पर इसका उपयोग करने वाले लोगों के लिए आवश्यक नहीं है।
मैं काट लूंगा !!! खुद के द्वारा मोनाड्स वास्तव में हास्केल के लिए एक जेल डीएट्रे नहीं हैं (हास्केल के शुरुआती संस्करणों में भी नहीं था)।
आपका सवाल थोड़ा सा है जैसे "C ++ जब मैं वाक्यविन्यास को देखता हूं, तो मैं बहुत ऊब जाता हूं। लेकिन टेम्पलेट C ++ का एक अत्यधिक विज्ञापित फीचर है इसलिए मैंने किसी अन्य भाषा में कार्यान्वयन पर ध्यान दिया"।
हास्केल प्रोग्रामर का विकास एक मजाक है, इसे गंभीरता से लेने का मतलब नहीं है।
हास्केल में एक कार्यक्रम के उद्देश्य के लिए एक मोनाड एक प्रकार का वर्ग मोनाड का एक उदाहरण है, जो कहना है, यह एक प्रकार है जो संचालन के एक निश्चित छोटे सेट का समर्थन करने के लिए होता है। हास्केल को उन प्रकारों के लिए विशेष समर्थन है जो मोनाड प्रकार वर्ग को लागू करते हैं, विशेष रूप से वाक्यात्मक समर्थन। व्यावहारिक रूप से यह जो परिणाम है, उसे "प्रोग्रामेबल सेमी-कोलोन" के रूप में संदर्भित किया गया है। जब आप इस कार्यक्षमता को हास्केल की कुछ अन्य विशेषताओं (प्रथम श्रेणी के कार्यों, डिफ़ॉल्ट रूप से आलस्य) के साथ जोड़ते हैं, तो आपको जो कुछ चीजें मिलती हैं उन्हें लागू करने की क्षमता है क्योंकि पुस्तकालयों को पारंपरिक रूप से भाषा की विशेषताएं माना जाता है। आप उदाहरण के लिए, एक अपवाद तंत्र लागू कर सकते हैं। आप लाइब्रेरी के रूप में निरंतरता और कोरटाइन के लिए समर्थन लागू कर सकते हैं। हास्केल, भाषा के पास परिवर्तनशील चर के लिए कोई समर्थन नहीं है:
आप "शायद / पहचान / सुरक्षित डिवीजन मोनाड्स ???" के बारे में पूछते हैं। शायद मोनाड एक उदाहरण है कि आप एक पुस्तकालय के रूप में कैसे (बहुत सरल, केवल एक अपवाद) अपवाद को लागू कर सकते हैं।
आप सही हैं, संदेश लिखना और उपयोगकर्ता इनपुट पढ़ना बहुत अनूठा नहीं है। आईओ "सुविधा के रूप में भिक्षुओं" का एक घटिया उदाहरण है।
लेकिन पुनरावृति करने के लिए, अपने आप में एक ("मोनाड्स") बाकी भाषा से अलग-थलग होना जरूरी नहीं कि तुरंत उपयोगी दिखाई दे (C ++ 0x की एक बड़ी नई विशेषता संदर्भ संदर्भ है, इसका मतलब यह नहीं है कि आप इसे ले सकते हैं सी + + संदर्भ से बाहर है क्योंकि यह सिंटैक्स आपको परेशान करता है और आवश्यक रूप से उपयोगिता को देखता है)। एक प्रोग्रामिंग भाषा एक ऐसी चीज़ नहीं है जिसे आप बाल्टी में सुविधाओं का गुच्छा फेंककर प्राप्त करते हैं।
प्रोग्रामर सभी प्रोग्राम लिखते हैं, लेकिन समानताएं वहां समाप्त होती हैं। मुझे लगता है कि अधिकांश प्रोग्रामर जितना कल्पना कर सकते हैं, उससे कहीं अधिक प्रोग्रामर भिन्न हैं। किसी भी लंबे समय तक चलने वाली "लड़ाई", जैसे स्थैतिक चर टाइपिंग बनाम रनटाइम केवल प्रकार, स्क्रिप्टिंग बनाम संकलित, सी-शैली बनाम ऑब्जेक्ट-उन्मुख। आपको तर्कसंगत रूप से यह तर्क करना असंभव होगा कि एक शिविर हीन है, क्योंकि उनमें से कुछ प्रोग्रामिंग सिस्टम में उत्कृष्ट कोड को मंथन करते हैं जो मुझे व्यर्थ लगता है या यहां तक कि मेरे लिए अनुपयोगी है।
मुझे लगता है कि अलग-अलग लोग बस अलग तरह से सोचते हैं, और अगर आपको सिंटैक्टिक शुगर या विशेष रूप से अमूर्त द्वारा लुभाया नहीं जाता है जो केवल सुविधा के लिए मौजूद हैं और वास्तव में एक महत्वपूर्ण रनटाइम लागत है, तो हर तरह से ऐसी भाषाओं से दूर रहें।
मैं फिर भी आपको सलाह दूंगा कि आप कम से कम उन अवधारणाओं से खुद को परिचित करने की कोशिश करें जो आप दे रहे हैं। मेरे पास किसी ऐसे व्यक्ति के खिलाफ कुछ भी नहीं है जो वीभत्स रूप से शुद्ध-सी है, जब तक कि वे वास्तव में समझते हैं कि मेमने के भाव के बारे में क्या बड़ी बात है। मुझे संदेह है कि अधिकांश तुरंत एक प्रशंसक नहीं बनेंगे, लेकिन कम से कम यह उनके दिमाग के पीछे होगा जब उन्हें सही समस्या का पता चलता है कि ओम्बा के साथ हल करने के लिए ओह इतना आसान क्या होता।
और, सबसे बढ़कर, फैनबॉय बोलने से परेशान होने से बचने की कोशिश करें, खासकर उन लोगों द्वारा जो वास्तव में नहीं जानते कि वे किस बारे में बात कर रहे हैं।
हास्केल रेफ़रेंशियल ट्रांसपेरेंसी को लागू करता है : समान मापदंडों को देखते हुए, हर फ़ंक्शन हमेशा एक ही परिणाम देता है, चाहे आप कितनी बार उस फ़ंक्शन को कॉल करें।
इसका मतलब है, उदाहरण के लिए, कि हास्केल पर (और मोनाड के बिना) आप एक यादृच्छिक संख्या जनरेटर को लागू नहीं कर सकते। C ++ या Java में आप ऐसा कर सकते हैं कि वैश्विक चर का उपयोग करते हुए, यादृच्छिक जनरेटर के मध्यवर्ती "बीज" मूल्य को संग्रहीत करें।
हास्केल पर वैश्विक चरों के समकक्ष मोनाड हैं।
Random
ऑब्जेक्ट में परिवर्तनशील चर का उपयोग करके किया जाता है ।
एक पुराने प्रश्न की तरह लेकिन यह वास्तव में अच्छा है, इसलिए मैं जवाब दूंगा।
आप कोड के ब्लॉक के रूप में भिक्षुओं के बारे में सोच सकते हैं, जिसके लिए आपका पूरा नियंत्रण है कि उन्हें कैसे निष्पादित किया जाता है: कोड की प्रत्येक पंक्ति को क्या लौटना चाहिए, क्या निष्पादन किसी भी बिंदु पर रुकना चाहिए, क्या प्रत्येक पंक्ति के बीच कुछ अन्य प्रसंस्करण होना चाहिए।
मैं उन चीजों के कुछ उदाहरण दूंगा जो कि भिक्षुओं को सक्षम बनाती हैं अन्यथा मुश्किल होगा। इन उदाहरणों में से कोई भी हास्केल में नहीं है, सिर्फ इसलिए कि मेरा हास्केल ज्ञान थोड़ा अस्थिर है, लेकिन वे सभी उदाहरण हैं कि हास्केल ने भिक्षुओं के उपयोग को कैसे प्रेरित किया है।
पारसर्स
आम तौर पर, यदि आप किसी प्रकार का पार्सर लिखना चाहते हैं, तो प्रोग्रामिंग भाषा को लागू करने के लिए कहें, आपको या तो बीएनएफ विनिर्देश को पढ़ना होगा और इसे पार्स करने के लिए लूप कोड का एक पूरा गुच्छा लिखना होगा, या आपको एक कंपाइलर कंपाइलर का उपयोग करना होगा जैसे फ्लेक्स, बाइसन, याक आदि। लेकिन मोनाड्स के साथ, आप हास्केल में एक प्रकार का "कंपाइलर पार्सर" बना सकते हैं।
पार्सर्स वास्तव में या तो मोनड्स या विशेष-प्रयोजन भाषाओं जैसे कि याक, बाइसन आदि के बिना नहीं किया जा सकता है।
उदाहरण के लिए, मैंने IRC प्रोटोकॉल के लिए BNF भाषा विनिर्देश लिया :
message = [ ":" prefix SPACE ] command [ params ] crlf
prefix = servername / ( nickname [ [ "!" user ] "@" host ] )
command = 1*letter / 3digit
params = *14( SPACE middle ) [ SPACE ":" trailing ]
=/ 14( SPACE middle ) [ SPACE [ ":" ] trailing ]
nospcrlfcl = %x01-09 / %x0B-0C / %x0E-1F / %x21-39 / %x3B-FF
; any octet except NUL, CR, LF, " " and ":"
middle = nospcrlfcl *( ":" / nospcrlfcl )
trailing = *( ":" / " " / nospcrlfcl )
SPACE = %x20 ; space character
crlf = %x0D %x0A ; "carriage return" "linefeed"
और इसे F # में कोड की लगभग 40 पंक्तियों तक घटा दिया (जो एक और भाषा है जो भिक्षुओं का समर्थन करती है)
type UserIdentifier = { Name : string; User: string; Host: string }
type Message = { Prefix : UserIdentifier option; Command : string; Params : string list }
let space = character (char 0x20)
let parameters =
let middle = parser {
let! c = sat <| fun c -> c <> ':' && c <> (char 0x20)
let! cs = many <| sat ((<>)(char 0x20))
return (c::cs)
}
let trailing = many item
let parameter = prefixed space ((prefixed (character ':') trailing) +++ middle)
many parameter
let command = atLeastOne letter +++ (count 3 digit)
let prefix = parser {
let! name = many <| sat (fun c -> c <> '!' && c <> '@' && c <> (char 0x20)) //this is more lenient than RFC2812 2.3.1
let! uh = parser {
let! user = maybe <| prefixed (character '!') (many <| sat (fun c -> c <> '@' && c <> (char 0x20)))
let! host = maybe <| prefixed (character '@') (many <| sat ((<>) ' '))
return (user, host)
}
let nullstr = function | Some([]) -> null | Some(s) -> charsString s | _ -> null
return { Name = charsString name; User = nullstr (fst uh); Host = nullstr (snd uh) }
}
let message = parser {
let! p = maybe (parser {
let! _ = character ':'
let! p = prefix
let! _ = space
return p
})
let! c = command
let! ps = parameters
return { Prefix = p; Command = charsString c; Params = List.map charsString ps }
}
F # का मोनाड सिंटैक्स हास्केल की तुलना में काफी बदसूरत है, और मैं संभवतः इसे थोड़ा सुधार सकता था - लेकिन घर ले जाने की बात यह है कि संरचनात्मक रूप से, पार्सर कोड बीएनएफ के समान है। इतना ही नहीं इसने बिना मोनाड्स (या पार्सर जनरेटर) के बहुत अधिक काम लिया होगा, यह विनिर्देशन के लगभग कोई समानता नहीं थी, और इस तरह दोनों को पढ़ने और बनाए रखने के लिए भयानक था।
कस्टम मल्टीटास्किंग
आम तौर पर, मल्टीटास्किंग को ओएस फीचर के रूप में माना जाता है - लेकिन मोनाड्स के साथ, आप अपने खुद के शेड्यूलर को लिख सकते हैं जैसे कि प्रत्येक निर्देश मोनड के बाद, प्रोग्राम शेड्यूलर पर नियंत्रण पारित करेगा, जो फिर निष्पादित करने के लिए एक और सनक का चयन करेगा।
एक व्यक्ति ने गेम लूप्स (फिर एफ # में) को नियंत्रित करने के लिए एक "कार्य" मोनाड बनाया , ताकि प्रत्येक मशीन पर काम करने वाली एक राज्य मशीन के रूप में सब कुछ लिखने के बजाय Update()
, वह सभी निर्देशों को लिख सके जैसे कि वे एक ही कार्य कर रहे थे ।
दूसरे शब्दों में, ऐसा कुछ करने के बजाय:
class Robot
{
enum State { Walking, Shooting, Stopped }
State state = State.Stopped;
public void Update()
{
switch(state)
{
case State.Stopped:
Walk();
state = State.Walking;
break;
case State.Walking:
if (enemyInSight)
{
Shoot();
state = State.Shooting;
}
break;
}
}
}
आप कुछ ऐसा कर सकते हैं:
let robotActions = task {
while (not enemyInSight) do
Walk()
while (enemyInSight) do
Shoot()
}
LINQ to SQL
LINQ to SQL वास्तव में एक सन्यासी का उदाहरण है, और इसी तरह की कार्यक्षमता हास्केल में आसानी से लागू की जा सकती है।
जब से मुझे वह सब याद नहीं आया, मैं विवरण में नहीं आऊंगा , लेकिन एरिक मीजर ने इसे अच्छी तरह समझाया है ।
यदि आप GoF पैटर्न से परिचित हैं, तो मोनाडर्स डैकोरेटर पैटर्न और बिल्डर पैटर्न की तरह होते हैं, जो एक रेडियोधर्मी बैजर द्वारा काटे गए स्टेरॉयड पर एक साथ होते हैं।
ऊपर बेहतर उत्तर हैं, लेकिन मेरे द्वारा देखे गए कुछ विशिष्ट लाभ हैं:
मोनाड्स कोर प्रकार को बदलने के बिना अतिरिक्त गुणों के साथ कुछ कोर प्रकार को सजाते हैं। उदाहरण के लिए, एक सनक "स्ट्रिंग" उठा सकता है और "isWellFormed", "Profanity "या" isPalindrome "आदि जैसे मान जोड़ सकता है।
इसी तरह, मोनाड्स एक सरल प्रकार को संग्रह प्रकार में परिवर्तित करने की अनुमति देते हैं
भिक्षु इस उच्च-क्रम वाले स्थान में कार्यों के देर से बंधन की अनुमति देते हैं
मोनैड्स उच्च-क्रम वाले स्थान में एक मनमाना डेटा प्रकार के साथ मनमाने कार्यों और तर्कों को मिलाने की अनुमति देते हैं
संन्यासी एक अशुद्ध, स्टेटफुल बेस के साथ शुद्ध, स्टेटलेस कार्यों को सम्मिश्रण करने की अनुमति देते हैं, ताकि आप यह जान सकें कि परेशानी कहाँ है
जावा में एक सन्यासी का एक परिचित उदाहरण सूची है। यह सूची के बारे में जानकारी जोड़ते हुए कुछ कोर क्लास लेता है, जैसे स्ट्रिंग, और लिस्ट के मोनड स्पेस में इसे "लिफ्ट" करता है। फिर यह उस जगह में नए कार्यों को बांधता है जैसे get (), getFirst (), add (), खाली (), आदि।
बड़े पैमाने पर, कल्पना करें कि एक कार्यक्रम लिखने के बजाय, आपने बस एक बड़ा बिल्डर (GoF पैटर्न के रूप में) लिखा है, और अंत में स्पैट में बिल्ड () विधि जो भी प्रोग्राम का उत्पादन करने वाला था, उसका उत्तर था। और यह कि आप मूल कोड को फिर से देखे बिना अपने ProgramBuilder में नए तरीके जोड़ सकते हैं। यही कारण है कि भिक्षु एक शक्तिशाली डिजाइन मॉडल हैं।