2013-08-05 9 views
6

मैं पहली बार के लिए एडवर्ड Kmett के लेंस पुस्तकालय का उपयोग कर रहा है, और यह नहीं बल्कि अच्छा लग रहा है, लेकिन मैं कोई समस्या में भाग ...अस्तित्व के प्रकारों के साथ लेंस का उपयोग करने में असमर्थता के आसपास कैसे काम करें?

पर [1] बताते हैं कि अस्तित्व परिमाणकों makeLenses बाधित सवाल। मैं वास्तव में कुछ फैशन में लेंस के साथ अस्तित्व का उपयोग करना चाहता हूं।

पृष्ठभूमि के रूप में, मैं कक्षा है:

class (TextShow file, Eq file, Ord file, Typeable file) => File file where 
    fromAnyFile :: AnyFile -> Maybe file 
    fileType :: Simple Lens file FileType 
    path :: Simple Lens file Text.Text 
    provenance :: Simple Lens file Provenance 

वास्तविक प्रश्न के लिए, मैं प्रकार करना चाहते हैं:

data AnyFile = forall file . File file => AnyFile { _anyFileAnyFile :: File } 

और मैं पंक्तियों के साथ कुछ लिखने में सक्षम होना चाहता हूँ का:

instance File AnyFile where 
    fromAnyFile (AnyFile file) = cast file 
    fileType (AnyFile file) = fileType . anyFile 
    path (AnyFile file) = path . anyFile 
    provenance (AnyFile file) = provenance . anyFile 

यह [1] में बताए गए कारणों के लिए काम नहीं करता है। अगर मैं -ddump-splices साथ संकलन के द्वारा डिबगिंग जानकारी के लिए GHC से पूछते हैं, मैं:

Haskell/Main.hs:1:1: Splicing declarations 
    makeLenses ''AnyFile ======> Haskell/Main.hs:59:1-20 

जोड़ ही खाली है, जो मेरे लिए इंगित करता है कि कोई घोषणाओं यह द्वारा उत्पादित कर रहे हैं। इस भाग में मैं उम्मीद करता हूं और समझता हूं कि मैंने पढ़ा है [1]।

मैं क्या जानना चाहता हूं कि मैं यह कैसे कर सकता हूं - समस्या के आसपास काम करने के लिए मैं क्या कर सकता हूं? इस पर तैरने से बचने के लिए मैं क्या कर सकता हूं? मैं रचनाकृत लेंस के पथ के माध्यम से अपने संरचनाओं के किसी भी भाग तक पहुंचने में सक्षम होना चाहता हूं, लेकिन क्योंकि मेरे पास Set AnyFile जैसे प्रकारों के साथ अन्य प्रकार के फ़ील्ड हैं, मैं तब तक ऐसा नहीं कर सकता जब तक कि मैं AnyFile की सामग्री को लेंस के साथ एक्सेस नहीं कर सकता।

[1] Existential quantifier silently disrupts Template Haskell (makeLenses). Why?

+0

बस किसी के लिए सोचने के लिए, मैंने नीचे दिए गए सुझाव का उपयोग करना था; परिभाषा 'लेंस (\ (AnyFile फ़ाइल) -> फ़ाइल होने की आवश्यकता है) (\ _ मान -> AnyFile मान) '। –

उत्तर

7

सबसे खराब स्थिति में, आप हमेशा लेंस अपने आप को बिल्कुल खाका हास्केल पर निर्भर रहे बिना लागू कर सकते हैं।

उदाहरण के लिए, एक गेटर और अपने प्रकार के लिए एक सेटर समारोह को देखते हुए, आप lens समारोह का उपयोग कर एक लेंस बना सकते हैं:

lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b 

मेरा मानना ​​है कि यह सबसे शक्तिशाली विकल्प नहीं हो सकता है, लेकिन यह निश्चित है सबसे आसान।

मैं कैसे अपने मामले के लिए यह करने के लिए (या सामान्य रूप में अस्तित्व प्रकार के साथ) पता नहीं है, लेकिन यहाँ एक रिकॉर्ड का उपयोग कर एक छोटी सी उदाहरण है:

data Foo = Foo { _field :: Int } 
foo = lens _field (\ foo new -> foo { _field = new }) 

उम्मीद है कि इस विचार को अच्छी तरह से लागू करने के लिए पर्याप्त दिखाता है आपके कोड में

+0

हम्म ... मुझे लेंस फ़ंक्शन के बारे में पता नहीं था। धन्यवाद! दस्तावेज़ बल्कि, एर, बड़े हैं। :) मैं अब कुछ काम करने की कोशिश कर रहा हूं, और अगर यह करता है तो जवाब स्वीकार करेगा। :) –

+1

लेंस का प्रकार, कम से कम मेरे संस्करण में, 'फंक्टर एफ => (एस -> ए) -> (एस -> बी -> टी) -> (ए -> एफबी) -> एस -> फीट'। ठीक है। ऐसा लगता है कि कुछ प्रकार की निरंतरता गुजरने वाली चीज़, मैं शायद इसे समझ सकता हूं ... –

+0

ओह मैं देखता हूं। सही। मुझे केवल पहले दो मानकों की आवश्यकता है क्योंकि शेष लोग लेंस का हिस्सा हैं ... शायद दस्तावेज़ बता सकते हैं कि मेरे लिए क्या है। –

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