2015-10-07 7 views
6

मैं वर्तमान में प्रतिक्रियाशील केले के साथ एफआरपी सीख रहा हूं और यादृच्छिक कार्यों की एक धारा बनाना चाहता था।पॉलिमॉर्फिक कार्यों की एक ईवेंट स्ट्रीम बनाएं - संभव है? यदि हां, तो कैसे?

-- | take number generator, and some pulse event stream, generate random function stream 
mkRandom :: (Random a,RandomGen g) => g -> Event t b -> Event t ((a,a) -> a) 
mkRandom rng es = (\f -> \r -> fst $ f r) <$> (accumE first $ next <$> es) 
    where first = flip randomR rng 
     next _ prev range = randomR range g 
      where (a,g) = prev range 

ऐसा लगता है काम करने के लिए, मैं इस तरह इसका इस्तेमाल कर सकते हैं:: मैं इस के साथ आ गया है,

randFuncs = mkRandom rnd (pulse 1000 time) 
some = ($ (0,10::Int)) <$> randFuncs 

लेकिन निश्चित रूप से, जब मुझे लगता है कि धारा की संख्या उत्पन्न करने के लिए साझा करने का प्रयास एक अलग प्रकार:

some2 = ($ (0,10::Double)) <$> randFuncs 

टाइप चेकर शिकायत करता है, जो मैं समझता हूं। तब मैं निम्नलिखित करने के लिए समारोह सामान्यीकरण करने की कोशिश की:

mkRandom :: (RandomGen g) => g -> Event t b -> Event t (forall a. Random a => (a,a) -> a) 

फिर GHC अवैध बहुरूपी हस्ताक्षर के बारे में शिकायत और है कि क्या मैं ImpredicativeTypes सक्षम करना चाहते हैं। मैंने ऐसा किया और काफी समय से इसे काम करने के लिए सब कुछ एनोटेट करने की कोशिश की, लेकिन जीएचसी ने हमेशा शिकायत की कि यह प्रकारों से मेल नहीं खा सकता है।

मेरा सवाल है - क्या मैं चाहता हूं कि यह करना संभव हो? क्या मुझे वास्तव में इसके लिए अपरिवर्तनीय प्रकार की आवश्यकता है या क्या मैं इसे गलत कर रहा हूं?

मैंने सोचा कि रैंकेंटाइप्स इसके लिए पर्याप्त होना चाहिए, लेकिन मुझे अभी तक ऐसे एक्सटेंशन के साथ कोई अनुभव नहीं है।

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

संपादित करें:

रिकॉर्ड के लिए, अब उपयोगी प्रतिक्रिया के आधार पर मेरे समाधान है:

newtype RandomSource = Rand { getRand :: forall a. (Random a) => (a,a) -> [a] } 

-- | take number generator and some pulse event stream, generate randomness stream 
mkRandom :: RandomGen g => g -> Event t a -> Behavior t RandomSource 
mkRandom rng es = fst <$> (accumB (next id (id,rng)) $ next <$> es) 
    where next _ (_,rng) = (Rand $ flip randomRs g1, g2) 
      where (g1,g2) = split rng 

-- | take a rand. source, a range and a pulse, return stream of infinite lists of random numbers 
randStream :: Random a => Behavior t RandomSource -> (a,a) -> Event t b -> Event t [a] 
randStream funcs range pulse = ($ range) . getRand <$> funcs <@ pulse 
+1

मुझे बताया गया है कि प्रतिक्रियाशील-केले 1.0 (वर्तमान 'मास्टर') गैर-तुच्छ और पर्याप्त तरीकों से प्रकारों को सरल बना देगा, जैसे 'रैंकेंटीप्स' (कुछ परिदृश्यों में) की आवश्यकता नहीं है, तो आप इसे दे सकते हैं प्रयत्न। –

+1

@ErikAllik एपीआई प्रतिक्रियाशील-केला 1 के लिए बदलता है।0 मुख्य रूप से प्रकार पैरामीटर 'टी' चिंता करते हैं। हाथ में सवाल इस से असंबंधित है। –

उत्तर

7

ImpredicativeTypes एक अविश्वसनीय रूप से भंगुर विस्तार है कि वास्तव में समर्थित नहीं है या बनाए रखा और इतने तोड़ना जारी रखती है नए जीएचसी संस्करणों में आगे।

एक बहुत बेहतर काम विकल्प के लिए एक newtype आवरण के साथ एक साथ RankNTypes उपयोग करने के लिए है:

newtype PolyRandFun = PR { getPR :: forall a. Random a => (a,a) -> a) } 

यह आवश्यक है कि आप स्पष्ट रूप से लपेट और newtype निर्माता खोलने में, लेकिन अन्यथा इस तरह बहुरूपी कार्यों के आसपास पारित करने के लिए ठीक काम करता है।

दुर्भाग्य से मैं इस मामले में एक और समस्या की भविष्यवाणी करता हूं। विभिन्न Random a उदाहरण उनके यादृच्छिक जनरेटर का उपयोग अलग राशि का उपयोग करते हैं, और उदाहरण के मामले में IntegerInteger परिणाम बनाने के लिए उत्पन्न प्राचीन यादृच्छिक संख्याओं की मात्रा भी सीमा के आकार पर निर्भर करेगी। तो आप वास्तव में अपने कार्यों को कॉल करते समय उपयोग किए जाने वाले प्रकार और श्रेणी को जानने के बिना अगले g नहीं प्राप्त कर सकते हैं।

सौभाग्य से वहाँ System.Random एपीआई कि यह चारों ओर से प्राप्त कर सकते में एक समारोह है: split आप एक नई यादृच्छिक जनरेटर कि subcalculations में पारित किया जा सकता है जब आप वास्तव में पूरी तरह से स्वतंत्र रूप से कई यादृच्छिक मान उत्पन्न करने के लिए की जरूरत है देता है।

+1

हां, मैं पुष्टि कर सकता हूं कि 'इंप्रेडिएटिव टाइप्स' बहुत भंगुर है - लेकिन क्या आप कह सकते हैं _why_ यह बहुत कम रखरखाव है? मुझे लगता है कि यह 'रैंकएन' के बजाय एक प्राकृतिक विस्तार होना चाहिए। – leftaroundabout

+2

@ बाएंराउंडबाउट [साइमन पीजे द्वारा स्पष्टीकरण] (https://mail.haskell.org/pipermail/glasgow-haskell-users/2014- फरवरी/024684.html) –

+2

@ बाएंअराउंडबाउट, मैं व्यक्तिगत रूप से नहीं कर सकता, लेकिन मेरी धारणा यह है कि यह है एक "गहरी" समस्या। जीएचसी का प्रकार चेकर स्पष्ट रूप से इसे सही करने में असमर्थ है, और कोई भी नहीं जानता कि एक प्रकार का चेकर कैसे लिखना है जो सही है, अन्य सभी सुंदर चीजें प्रदान करता है, और अस्पष्ट मानव-पठनीय त्रुटि संदेश देता है। – dfeuer

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

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