मेरी प्रोग्राम की स्थिति, तीन मानों, a
, b
, और c
के होते प्रकार A
, B
, और C
के भीतर स्टेटफुल संगणना से मेल खाते हैं। विभिन्न कार्यों को विभिन्न मूल्यों तक पहुंच की आवश्यकता होती है। मैं State
मोनैड का उपयोग करके फ़ंक्शन लिखना चाहता हूं ताकि प्रत्येक कार्य केवल उस राज्य के टुकड़ों तक पहुंच सके जिसे इसे एक्सेस करने की आवश्यकता हो।मिक्स और राज्य इकाई
मैं निम्नलिखित प्रकार के चार कार्य किया है:
f :: State (A, B, C) x
g :: y -> State (A, B) x
h :: y -> State (B, C) x
i :: y -> State (A, C) x
यहाँ है कि कैसे मैं g
f
भीतर फोन: g'
समारोह बॉयलरप्लेट का एक बदसूरत टुकड़ा है कि लेकिन पुल कुछ नहीं करता है
f = do
-- some stuff
-- y is bound to an expression somewhere in here
-- more stuff
x <- g' y
-- even more stuff
where g' y = do
(a, b, c) <- get
let (x, (a', b')) = runState (g y) (a, b)
put (a', b', c)
return x
कि (A, B, C)
और (A, B)
के बीच का अंतर। यह मूल रूप से g
का एक संस्करण है जो 3-ट्यूपल राज्य पर चलता है, लेकिन तीसरे ट्यूपल आइटम को अपरिवर्तित छोड़ देता है। मैं उस बॉयलरप्लेट के बिना f
लिखने का एक तरीका ढूंढ रहा हूं। इस तरह हो सकता है कि कुछ:
f = do
-- stuff
x <- convert (0,1,2) (g y)
-- more stuff
कहाँ convert (0,1,2)
प्रकार State (a, b) x
की गणना धर्मान्तरित टाइप करने के लिए State (a, b, c) x
। इसी तरह, सभी प्रकार a
, b
, c
, d
के लिए:
convert (2,0,1)
State (c,a) x
State (a,b,c) x
करने के लिएconvert (0,1)
धर्मान्तरितState b x
State (a,b) x
-convert (0,2,1,0)
धर्मान्तरितState (c,b) x
State (a,b,c,d) x
करने के लिए
धर्मान्तरित मेरे प्रश्न:
- क्या राज्य मूल्यों को टुपल्स में डालने से बेहतर समाधान है? मैंने एक मोनड ट्रांसफॉर्मर स्टैक का उपयोग करने के बारे में सोचा। हालांकि, मुझे लगता है कि केवल तभी काम करता है, किसी भी दो कार्य
f
औरg
के लिए, या तोF
⊆G
याG
⊆F
, जहांF
राज्यf
औरG
द्वारा आवश्यक मूल्यों का वह समूह हैg
द्वारा आवश्यक राज्य मूल्यों का वह समूह है। क्या मैं उस बारे में गलत हूं? (ध्यान दें कि मेरे उदाहरण इस संपत्ति को पूरा नहीं करता है। उदाहरण के लिए,G
={a, b}
औरH
={b, c}
। न तो अन्य के एक सबसेट है।) - अगर वहाँ tuples के अलावा कोई बेहतर तरीका है, तो करने के लिए एक अच्छा तरीका है मैंने उल्लेख किया बॉयलरप्लेट से बचें? मैं बॉयलरप्लेट फ़ंक्शंस (नीचे देखें) के एक समूह के साथ एक फ़ाइल लिखने के लिए भी तैयार हूं, जब तक कि फ़ाइल स्वचालित रूप से एक बार उत्पन्न हो और फिर भूल जाए। क्या कोई बेहतर तरीका है? (मैंने लेंस के बारे में पढ़ा है, लेकिन उनकी जटिलता, बदसूरत वाक्यविन्यास, अनावश्यक सुविधाओं का विशाल सेट, और टेम्पलेट हास्केल पर निर्भर निर्भरता बंद है। क्या यह मेरी गलत धारणा है? क्या लेंस मेरी समस्या को इस तरह से हल कर सकते हैं जो उन समस्याओं से बचाता है ?)
(मेरे द्वारा वर्णित कार्यों को इस तरह कुछ दिखाई देगा।)
convert_0_1_2 :: State (a, b) x -> State (a, b, c) x
convert_0_1_2 f = do
(a, b, c) <- get
let (x, (a', b')) = runState f (a, b)
put (a', b', c)
return x
convert_0_2_1_0 :: State (c, b) x -> State (a, b, c, d) x
convert_0_2_1_0 f = do
(a, b, c, d) <- get
let (x, (b', c')) = runState f (b, c)
put (a, b', c', d)
return x
मैं इसे अपने आप उपयोग नहीं किया है, लेकिन यह 'तरह lens' के' zoom' बहुत ज्यादा लगता है: http://hackage.haskell.org/package/lens-4.13/docs/Control-Lens-Zoom.html #v: ज़ूम –
यह निर्भर प्रकारों के साथ आसान होना चाहिए, लेकिन हैशोकिस्ट नहीं है। – user3237465
'lens' + [' vinyl'] (https://hackage.haskell.org/package/vinyl) एक आधे रास्ते सभ्य hasochistic अनुभव के लिए बनाता है। 'च :: राज्य (ए, ए)()' और 'जी :: राज्य ए()': –