2013-11-21 9 views
6

मैं उच्च-आदेश लैम्ब्डा कैलकुस एन्कोडिंग में एक हास्केल फ़ंक्शन को उठाना चाहता हूं। यह ओलेग के टाइप किए गए टैगलेस फाइनल एन्कोडिंग से लगभग शब्दशः लिया जाता है।सामान्यीकृत बहु-पैरामीटर फ़ंक्शन उठाने के लिए टाइपक्लास ट्रिक्स

class Lam r where 
    emb :: a -> r a 
    (^) :: r (r a -> r a) -> (r a -> r a) 
    lam :: (r a -> r a) -> r (r a -> r a) 

instance Lam Identity where 
    emb = Identity 
    f^x = f >>= ($ x) 
    lam f = return (f . return =<<) -- call-by-value 

eval = runIdentity 

मैं Lamemb का उपयोग करते हुए मनमाने ढंग से हास्केल प्रकार एम्बेड कर सकते हैं, लेकिन मैं तो आवेदन के लिए (^) उपयोग नहीं कर सकते। इसके अलावा, उठाए गए कार्यों आलसी व्यवहार करेंगे। इसके बजाय, मुझे आवेदन द्वारा उन्हें आवेदन उठाना होगा।

emb1 :: (Applicative r, Lam r) 
    => (a -> b) -> r (r a -> r b) 
emb1 f = lam $ \ra -> f <$> ra 

emb2 :: (Applicative r, Lam r) 
    => (a -> b -> c) -> r (r a -> r (r b -> r c)) 
emb2 f = lam $ \ra -> lam $ \rb -> f <$> ra <*> rb 

emb3 :: (Applicative r, Lam r) 
    => (a -> b -> c -> d) 
    -> r (r a -> r (r b -> r (r c -> r d))) 
emb3 f = lam $ \ra -> lam $ \rb -> lam $ \rc -> f <$> ra <*> rb <*> rc 

>>> eval $ emb2 (+)^emb 1^emb 2 
3 

हालांकि, यह बहुत सारे बॉयलरप्लेट है। मैं एक जेनेरिक लिफ्टिंग फ़ंक्शन बनाना चाहता हूं जो किसी भी धैर्य समारोह के लिए काम करेगा। मुझे लगता है कि Printf के PrintfType या fixed-vector के Cont प्रकारों जैसे कुछ का उपयोग करना संभव होगा। मैं निर्दिष्ट कर सकता हूं कि मैं टाइप फ़ंक्शंस

type family Low h  o 
type instance Low ()  o = o 
type instance Low (a, h) o = a -> Low h o 

type family Lift r h  o 
type instance Lift r()  o = o 
type instance Lift r (a, h) o = r a -> r (Lift r h o) 

class Emb r h o where 
    embed :: Low h o -> r (Lift r h o) 

instance (Lam r) => Emb r() o where 
    embed = emb 

instance (Lam r, Applicative r, Emb r h o) => Emb r (a, h) o where 
    embed = ? 

पर निर्भर करता हूं लेकिन आमतौर पर इंजेक्शन समस्याओं के कारण, मैं इस विधि के माध्यम से बहुत फंस जाता हूं। मैं न्यूटाइप रैपर और स्कोप्ड प्रकार चर के वास्तव में भयानक संयोजन के साथ इंजेक्शनिविटी को हल करने में सक्षम था, लेकिन यह वास्तव में कभी भी चेक टाइप नहीं किया गया था।

क्या यह हास्केल में व्यक्त करना संभव है?

+0

मुझे जवाब नहीं पता, लेकिन अगला लिंक सहायक हो सकता है: http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html – wit

उत्तर

3

आप टैग रहित-अंतिम शैली में Ordinary and one-pass CPS transformation पर देखना चाह सकते हैं। चाल ऑब्जेक्ट भाषा में तीर प्रकार को सामान्यीकृत करना है। तथ्य यह है कि हम ऑब्जेक्ट भाषा (एम्बेडेड होने के लिए) में फ़ंक्शन प्रकारों के लिए अक्सर हास्केल के प्रकार कन्स्ट्रक्टर -> का उपयोग करते हैं, यह एक संयोग और सुविधा है। आम तौर पर, ऑब्जेक्ट फ़ंक्शंस केवल हास्केल फ़ंक्शंस को मैप नहीं करते हैं। संदर्भित किया जाता लेख में कोड ESymantics

-- How to interpret arrows and other types 
type family Arr (repr :: * -> *) (a :: *) (b :: *) :: * 

class ESymantics repr where 
    int :: Int -> repr Int 
    add :: repr Int -> repr Int -> repr Int 

    lam :: (repr a -> repr b) -> repr (Arr repr a b) 
    app :: repr (Arr repr a b) -> repr a -> repr b 

अब हम एक विशेष रेपर के आधार पर आगमन की व्याख्या करने के लिए पर्याप्त स्वतंत्रता है शामिल हैं। निर्दिष्ट आलेख सीपीएस उदाहरण के लिए एआर की व्याख्या करता है।

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

+0

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

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