जब मैं LYAH के आखिरी अध्याय के माध्यम से चला गया और ListZipper के साथ मुलाकात की, मैं अपने आप को एक काम है कि यह एक राज्य इकाई ताकि स्रोत कोड की तरह और अधिक स्पष्ट दिखेगा बनाने के लिए दे दी है समय, मैं राइटर मोनड का लाभ उठाकर इस प्रक्रिया के लिए एक लॉग रखना चाहता था, लेकिन मुझे नहीं पता था कि इन दो मोनाड्स को एक साथ कैसे जोड़ा जाए।हैकेल में मैं राज्य और लेखक दोनों का लाभ कैसे उठा सकता हूं?</p> <pre><code>manipList = do goForward goForward goBack </code></pre> <p>और एक ही है:
मेरे समाधान राज्य के अंदर रखने के लिए एक [स्ट्रिंग] था, और मेरे स्रोत कोड
import Control.Monad
import Control.Monad.State
type ListZipper a = ([a], [a])
-- move focus forward, put previous root into breadcrumbs
goForward :: ListZipper a -> ListZipper a
goForward (x:xs, bs) = (xs, x:bs)
-- move focus back, restore previous root from breadcrumbs
goBack :: ListZipper a -> ListZipper a
goBack (xs, b:bs) = (b:xs, bs)
-- wrap goForward so it becomes a State
goForwardM :: State (ListZipper a) [a]
goForwardM = state stateTrans where
stateTrans z = (fst newZ, newZ) where
newZ = goForward z
-- wrap goBack so it becomes a State
goBackM :: State (ListZipper a) [a]
goBackM = state stateTrans where
stateTrans z = (fst newZ, newZ) where
newZ = goBack z
-- here I have tried to combine State with something like a Writer
-- so that I kept an extra [String] and add logs to it manually
-- nothing but write out current focus
printLog :: Show a => State (ListZipper a, [String]) [a]
printLog = state $ \(z, logs) -> (fst z, (z, ("print current focus: " ++ (show $ fst z)):logs))
-- wrap goForward and record this move
goForwardLog :: Show a => State (ListZipper a, [String]) [a]
goForwardLog = state stateTrans where
stateTrans (z, logs) = (fst newZ, (newZ, newLog:logs)) where
newZ = goForward z
newLog = "go forward, current focus: " ++ (show $ fst newZ)
-- wrap goBack and record this move
goBackLog :: Show a => State (ListZipper a, [String]) [a]
goBackLog = state stateTrans where
stateTrans (z, logs) = (fst newZ, (newZ, newLog:logs)) where
newZ = goBack z
newLog = "go back, current focus: " ++ (show $ fst newZ)
-- return
listZipper :: [a] -> ListZipper a
listZipper xs = (xs, [])
-- return
stateZipper :: [a] -> (ListZipper a, [String])
stateZipper xs = (listZipper xs, [])
_performTestCase1 = do
goForwardM
goForwardM
goBackM
performTestCase1 =
putStrLn $ show $ runState _performTestCase1 (listZipper [1..4])
_performTestCase2 = do
printLog
goForwardLog
goForwardLog
goBackLog
printLog
performTestCase2 = do
let (result2, (zipper2, log2)) = runState _performTestCase2 $ stateZipper [1..4]
putStrLn $ "Result: " ++ (show result2)
putStrLn $ "Zipper: " ++ (show zipper2)
putStrLn "Logs are: "
mapM_ putStrLn (reverse log2)
है लेकिन समस्या यह मुझे नहीं लगता कि कि यह एक अच्छा उपाय है के बाद से मैं अपने बनाए रखने के लिए है लॉग मैन्युअल रूप से। क्या राज्य मोनड और राइटर मोनड मिश्रण करने का कोई वैकल्पिक तरीका है ताकि वे एक साथ काम कर सकें?
वही है जो मैं चाहता हूं!मैंने कोशिश की है और उनमें से दोनों (राइटर टी एंड स्टेटटी) अच्छी तरह से काम करते हैं, टाई! – Javran