मैं एक परियोजना एक स्थानीय संक्रमण समारोह के रूप में एक सेलुलर automaton को परिभाषित करने पर काम शुरू:एक effectful समारोह Memoizing
newtype Cellular g a = Cellular { delta :: (g -> a) -> a }
जब भी g
एक Monoid
है, यह लागू करने से पहले ध्यान देने के स्थानांतरण से एक वैश्विक संक्रमण परिभाषित करना संभव है स्थानीय संक्रमण। यह हमें निम्नलिखित step
समारोह देता है:
step :: Monoid g => Cellular g a -> (g -> a) -> (g -> a)
step cell init g = delta cell $ init . (g <>)
अब, हम बस iterate
का उपयोग करके आटोमैटिक मशीन चला सकते हैं। चरणों में से हर एक के अनुरूप बनाएं memo
द्वारा फिर से संगणना की: और हम एक बहुत बचा सकता है (यह सचमुच घंटे की बचत होती है और मैं एक बहुत मतलब है):
run :: (Monoid g, Memoizable g) => Cellular g a -> (g -> a) -> [g -> a]
run cell = iterate (memo . step cell)
मेरे समस्या यह है कि मैं इतना है कि CelluarT
करने के लिए Cellular
सामान्यीकृत है मैं स्थानीय नियमों में साइड इफेक्ट का उपयोग करने में सक्षम होगा (जैसे एक यादृच्छिक पड़ोसी को कॉपी):
newtype CellularT m g a = Cellular { delta :: (g -> m a) -> m a }
हालांकि, मैं केवल प्रभाव चलाने के लिए चाहते हैं एक बार तो यह है कि अगर आप एक सेल पूछना कई बार क्या इसका मूल्य है, जवाब सभी संगत हैं। memo
हमें यहां विफल कर देता है क्योंकि यह इसके परिणाम के बजाय प्रभावशाली गणना बचाता है।
मुझे उम्मीद नहीं है कि यह असुरक्षित सुविधाओं का उपयोग किए बिना प्राप्त करने योग्य नहीं है। मैंने इसे एक जाना है करने के लिए मूल्यों को पहले से ही गणना की स्टोर करने के लिए unsafePerformIO
, एक IORef
और एक Map g a
का उपयोग कर की कोशिश की है:
memoM :: (Ord k, Monad m) => (k -> m v) -> (k -> m v)
memoM =
let ref = unsafePerformIO (newIORef empty) in
ref `seq` loopM ref
loopM :: (Monad m, Ord k) => IORef (Map k v) -> (k -> m v) -> (k -> m v)
loopM ref f k =
let m = unsafePerformIO (readIORef ref) in
case Map.lookup k m of
Just v -> return v
Nothing -> do
v <- f k
let upd = unsafePerformIO (writeIORef ref $ insert k v m)
upd `seq` return v
लेकिन यह अप्रत्याशित तरीके से व्यवहार करती है: memoM putStrLn
सही ढंग से memoized है, जबकि memoM (\ str -> getLine)
के बावजूद प्राप्त करने में कठिनाई लाइनों रहता है उसी तर्क को पारित किया जा रहा है।
आप कौन सी मेमो लाइब्रेरी का उपयोग कर रहे हैं? [Memoize] (https://hackage.haskell.org/package/memoize)? – Cirdec
आपके डेटा प्रकार ['Cont' और' ContT'] के बराबर हैं (https://hackage.haskell.org/package/transformers/docs/Control-Monad-trans-Cont.html)। 'सेलुलर जीए = कंट एजी' टाइप करें और 'सेलुलर टी एमजी = कंटेट एमजी' – Cirdec