2010-10-15 16 views
14

हास्केल एक शुद्ध कार्यात्मक प्रोग्रामिंग भाषा है।हास्केल और राज्य

मेरा प्रश्न है: कई राज्यों से जुड़े समस्याओं को हल करने के लिए हास्केल का उपयोग करने के फायदे और नुकसान क्या हैं, उदाहरण के लिए जीयूआई प्रोग्रामिंग या गेम प्रोग्रामिंग?

इसके अलावा एक माध्यमिक प्रश्न: एक कार्यात्मक तरीके से राज्य को संभालने के लिए कौन सी विधियां हैं?

अग्रिम धन्यवाद।

+0

http://www.haskell.org/all_about_monads/html/statemonad.html –

+4

एक कार्यात्मक भाषा में राज्य को संभालने में राज्य को कार्यों के चारों ओर गुजरना शामिल है। मोनाड्स इसे सरल बनाते हैं। – tylermac

+0

@tylermac मैं कभी भी monads को समझने में सक्षम नहीं था, ठीक है, मैं यह नहीं कह सकता कि मैं बेवकूफ हूँ, कम से कम मैं सीएस में बीएस हूं, लेकिन monads ... क्या आप अच्छे ट्यूटोरियल जानते हैं? – Andrey

उत्तर

17

मैं पहली बार अपने दूसरे सवाल का जवाब देने जा रहा हूँ। हास्केल (और अन्य एफपी भाषाओं) में परिवर्तनीय स्थिति को संभालने के लिए वास्तव में कई तरीके हैं। सबसे पहले, हास्केल आईओओ में IORef और mvar संरचनाओं के माध्यम से उत्परिवर्तनीय स्थिति का समर्थन करता है। इनका उपयोग करना अनिवार्य भाषाओं से प्रोग्रामर से बहुत परिचित होगा। STRef और TMVar, साथ ही साथ परिवर्तनीय सरणी, पॉइंटर्स और कई अन्य परिवर्तनीय डेटा जैसे विशेष संस्करण भी हैं। सबसे बड़ी कमी यह है कि ये आम तौर पर केवल आईओ या अधिक विशिष्ट मोनैड के भीतर उपलब्ध होते हैं।

एक कार्यात्मक भाषा में राज्य अनुकरण करने का सबसे आम तरीका स्पष्ट रूप से एक कार्य तर्क के रूप में राज्य को गुजर रहा है और मूल्य वापस कर दिया गया है। उदाहरण के लिए:

randomGen :: Seed -> (Int, Seed) 

यहाँ randomGen एक बीज पैरामीटर लेता है और एक नया बीज देता है। हर बार जब आप इसे कॉल करते हैं, तो आपको अगले पुनरावृत्ति के लिए बीज का ट्रैक रखने की आवश्यकता होती है। यह तकनीक हमेशा राज्य के गुजरने के लिए उपलब्ध है, लेकिन यह जल्दी से थकाऊ हो जाता है।

शायद सबसे आम हास्केल दृष्टिकोण इस राज्य को गुजरने के लिए एक मोनैड का उपयोग करना है। हम इस के साथ randomGen की जगह ले सकता:

-- a Random monad is simply a Seed value as state 
type Random a = State Seed a 

randomGen2 :: Random Int 
randomGen2 = do 
    seed <- get 
    let (x,seed') = randomGen seed 
    put seed' 
    return x 

अब किसी भी कार्य करता है जो की जरूरत है एक PRNG रैंडम इकाई के भीतर चला सकते हैं उन्हें आवश्यकतानुसार अनुरोध करने के लिए। आपको केवल प्रारंभिक स्थिति और गणना प्रदान करने की आवश्यकता है।

runRandomComputation :: Random a -> Seed -> a 
runRandomComputation = evalState 

(ध्यान दें कि यादृच्छिक जीन 2 की परिभाषा को काफी कम करता है; मैंने सबसे स्पष्ट संस्करण चुना है)।

यदि आपकी यादृच्छिक गणना को IO तक पहुंच की आवश्यकता है, तो आप राज्य के 0,के मोनैड ट्रांसफार्मर संस्करण का उपयोग करें।

विशेष नोट ST मोनैड है, जो अनिवार्य रूप से आईओ-विशिष्ट उत्परिवर्तनों को आईओ के बाकी हिस्सों से दूर करने के लिए एक तंत्र प्रदान करता है। एसटी मोनड एसटीआरआईएफ प्रदान करता है, जो डेटा के एक परिवर्तनीय संदर्भ हैं, और म्यूटेबल सरणी भी हैं।अनुसूचित जनजाति का उपयोग करना, यह इस तरह बातें निर्धारित करना संभव है:

randomList :: Seed -> [Int] 

जहां [इंट] यादृच्छिक संख्या की एक अनंत सूची (यह चक्र के अंत में अपने PSRG के आधार पर होगा) प्रारंभिक बीज आप इसे देने से है।

अंत में, Functional Reactive Programming है। इसके लिए वर्तमान में सबसे प्रमुख पुस्तकालय Yampa और Reactive हैं, लेकिन अन्य भी देख रहे हैं। एफआरपी के विभिन्न कार्यान्वयन के भीतर परिवर्तनीय राज्य के कई दृष्टिकोण हैं; उनके थोड़े उपयोग से वे अकसर क्यूटी या जीटीके + (जैसे घटनाओं के लिए श्रोताओं को जोड़ना) में एक सिग्नलिंग फ्रेमवर्क के लिए अवधारणा में समान दिखते हैं।

अब, पहले प्रश्न के लिए। मेरे लिए, सबसे बड़ा फायदा यह है कि उत्परिवर्तनीय राज्य प्रकार के स्तर पर दूसरे कोड से अलग होता है। इसका अर्थ यह है कि जब तक कोड हस्ताक्षर में स्पष्ट रूप से उल्लेख नहीं किया जाता है तब तक कोड गलती से राज्य को संशोधित नहीं कर सकता है। यह पठनीय राज्य बनाम केवल पढ़ने योग्य राज्य (रीडर मोनड बनाम राज्य मोनड) का बहुत अच्छा नियंत्रण देता है। मुझे इस तरह से मेरे कोड को ढूढ़ने में बहुत उपयोगी लगता है, और यदि कोई फ़ंक्शन अप्रत्याशित रूप से स्थिति को बदल सकता है तो यह केवल प्रकार के हस्ताक्षर से बताने में सक्षम होना उपयोगी है।

मैं व्यक्तिगत रूप से हास्केल में उत्परिवर्तनीय स्थिति का उपयोग करने के बारे में कोई आरक्षण नहीं करता हूं। सबसे बड़ी कठिनाई यह है कि राज्य को उस चीज़ को जोड़ने के लिए कठिन हो सकता है जिसकी आवश्यकता पहले नहीं थी, लेकिन वही बात अन्य भाषाओं में कठिन होगी जो मैंने समान कार्यों (सी #, पायथन) के लिए उपयोग की है।

+0

यहां 'बीज' क्या है? मैंने इसे अपनी फ़ाइल के शीर्ष पर int के रूप में परिभाषित करने की कोशिश की ('टाइप बीज = Int') लेकिन त्रुटि प्राप्त करें (शो (रैंडम इंट)) के लिए कोई उदाहरण नहीं है (मैंने शुरुआत में आपके कोड के सिद्धांत का उपयोग किया था, जो नहीं था काम, इसलिए इसे कॉपी-पेस्ट करने की कोशिश की और फिर यह त्रुटि मिली)। –

+0

यह एक वास्तविक कार्यान्वयन की तुलना में अधिक छद्म कोड है। 'बीज 'एक अमूर्त प्रकार है जो पीआरएनजी के राज्य-निर्भर डेटा का प्रतिनिधित्व करता है। मैं पीएनआरजी का उपयोग कर रहा था क्योंकि यह राज्य के एल्गोरिदम के वर्ग का एक प्रसिद्ध उदाहरण है। यदि आपको यादृच्छिक संख्या जनरेटर की आवश्यकता है तो मैं 'mwc-random' या' mersenne-random 'जैसे पैकेज की अनुशंसा करता हूं। –

+0

उत्तर के लिए धन्यवाद - मैं वास्तव में एक पीआरएनजी का उपयोग करने के बजाय moads को समझने की कोशिश कर रहा हूं, लेकिन मुझे लगता है कि यह वास्तव में एक अच्छा उदाहरण है। मैं पूरी तरह से अटक गया हूँ। मैंने कुछ घंटों पहले इस पर एक सवाल पूछा था, लेकिन अब और भी उलझन में हूँ! http://stackoverflow.com/questions/23595363/simple-haskell-monad-random-number/ –

11

जबकि मुझे संदेह नहीं है कि लोग "राज्य मोनैड का उपयोग" के साथ जवाब देंगे, मैं एक और उपयोगी विधि इंगित करना चाहता हूं: कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग (याम्पा या अन्यथा)।

2

आम तौर पर आप जो करना चाहते हैं वह एक स्टेटट और आईओ के साथ एक मोनाड ट्रांसफार्मर का उपयोग करता है, क्योंकि दृश्य (जीयूआई) को जवाब देने के लिए आईओ की आवश्यकता होती है, हालांकि एक बार जब आपने newtype में अपना मोनाड ट्रांसफार्मर परिभाषित किया है, तो आप केवल MonadState इंटरफ़ेस के साथ गेम तर्क के हस्ताक्षर बनाएं, इस तरह आपको अभी भी गैर-आईओ-नेस परिवर्तनों का लाभ है। समझा नीचे कोड मैं क्या मतलब है:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
import Control.Monad.State 

data GameState = GameState { ... } deriving (Show) 
newtype GameMonad a = GameMonad (StateT GameState IO a) 
         deriving (Monad, MonadState GameState, MonadIO) 

-- This way, now you have a monad with the state of the info 
-- what would you like now is being able to modify the state, without actually 
-- having IO capabilites. 

movePlayerOnState :: (MonadState GameState) m => Position -> m() 
-- In this function we get the state out of the state monad, and then we modify 
-- with a pure function, then put the result back again 

-- Other times you would like to have the GUI API available, requiring the IO monad 
-- for that 
renderGameFromState :: MonadIO m => GameState -> m() 
-- in this method you would use liftIO method to call the GUI API 

इस कोड (यदि आप monads समझ में नहीं है, लेकिन अंगूठे का मेरा नियम है, यह पता लगाने क्या राज्य इकाई के लिए है, समझने की क्या इकाई ट्रांसफॉर्मर हैं काफी जटिल है बिना यह समझने की आवश्यकता है कि वे कैसे काम करते हैं) और स्टेटट मोनड का उपयोग कैसे करें।

मुझे लगता है कि उपयोगी हो सकता है एक Sokoban परियोजना मैं अन्य टीम के साथ किया था करने के लिए आप बात कर सकते हैं, यह जीयूआई के रूप में ncurses का उपयोग करता है, लेकिन आप तर्क के विचार प्राप्त कर सकते हैं और कैसे हम खेल पर राज्यों में कामयाब

http://github.com/roman/HaskBan

शुभकामनाएं।

4

बहुत सारे राज्य से जुड़े समस्याओं को हल करने के लिए हास्केल का उपयोग करने के फायदे और नुकसान क्या हैं, उदाहरण के लिए जीयूआई प्रोग्रामिंग या गेम प्रोग्रामिंग?

लाभ यह है कि, भले ही आप विशेष रूप से पवित्रता का लाभ लेने नहीं कर रहे हैं, हास्केल बस एक अच्छा भाषा है।

प्रथम श्रेणी के कार्यों - 2010 में एक बड़ा सौदा नहीं होना चाहिए, लेकिन यह है। पैटर्न मिलान के साथ बीजगणितीय प्रकार। प्रकार अनुमान के साथ शक्तिशाली स्थिर प्रकार की जांच। स्वच्छ वाक्यविन्यास। प्रथम श्रेणी की सहमति, एसटीएम, और थ्रेड-फ्री शुद्ध समांतरता। एक अच्छा संकलक। पुस्तकालयों के टन और हर दिन। एक सक्रिय, सहायक समुदाय।

ये शुद्धता या आलस्य जैसे बड़े विचारधारात्मक निर्णय नहीं हैं। वे सिर्फ अच्छे विचार हैं।वे चीजें हैं जो ज्यादातर भाषाओं में हो सकती हैं, लेकिन बहुत से लोग नहीं करते हैं।

+0

क्या आप मुझे बता सकते हैं कि प्रथम श्रेणी की सहमति क्या है? –

4

एक राज्य मोनड एक जीयूआई या हास्केल में एक गेम मॉडल करने का सबसे खराब तरीका है। मुझे लगता है कि दूसरा सबसे अच्छा विकल्प दोनों मामलों में समेकन का उपयोग करना है। हालांकि, पॉल द्वारा सबसे अच्छा विकल्प उल्लेख किया गया है: कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग (एफआरपी)।

व्यक्तिगत रूप से मैं तीरलाइट एफआरपी (एएफआरपी) की वकालत करता हूं, जो मुझे लगता है कि पहले यम्पा के रूप में लागू किया गया था और बाद में थोड़ा अधिक उपयोगी एनिमस के रूप में फोर्क किया गया था। हालांकि, यम्पा जल्दी ही इसकी सीमा तक पहुंच गया है, इसलिए मैंने netwire नामक एक और अधिक शक्तिशाली, अधिक अभिव्यक्तिपूर्ण लाइब्रेरी लिखी है, जिसमें पिछले दो में कुछ वैचारिक सुधार भी हैं।

इसके सार में AFRP एक कार्यात्मक राज्य प्रणाली है। यह कार्यात्मक है कि उस राज्य को परिवर्तनीय चर बदलने के रूप में मॉडलिंग नहीं किया गया है, बल्कि कार्यों को उत्परिवर्तित किया गया है। यह क्लीनर है और राज्य के monads जैसे किसी भी अनिवार्य प्रोग्रामिंग की आवश्यकता नहीं है।

संबंधित मुद्दे