मैं एक आईओ मोनैड के साथ एक ऐपस्टेट बनाने के लिए Combine state with IO actions में दी गई सलाह का पालन करने का प्रयास कर रहा हूं। जो मैंने प्राप्त किया है वह यह है:मैं वास्तव में आईओ के साथ एक स्टेटटी मोनड कैसे निष्पादित करूं?
module Main where
import Control.Monad.State
import Control.Monad.Trans
data ST = ST [Integer] deriving (Show)
type AppState = StateT ST IO
new = ST []
append :: Integer -> State ST()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: State ST Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
script = do
append 5
append 10
append 15
sumST
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
let (res, st) = runState script new
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runStateT myMain (ST [15])
इसका कुछ हिस्सा मुझे नहीं मिल रहा है। यह मुझे बहुत परेशान करता है कि मेरे पास script
और myMain
औरmain
है। यह मुझे परेशान करता है कि मुझे runState
को myMain
के भीतर निष्पादित करना होगा और मुझे अपने मुख्य कार्य में runStateT
में प्रारंभिक स्थिति को फ़ीड करना होगा। मैं अपनी "स्क्रिप्ट" रखना चाहता हूं, इसलिए सीधे मेरे मुख्य कार्य में बोलने के लिए, क्योंकि मेरे मेन का पूरा बिंदु परिशिष्ट चलाने और प्रिंट ऑपरेशन के ठीक आगे सीधे चलाने के लिए सक्षम होना है। मुझे लगता है कि मैं इसके बजाय यह करने के लिए, सक्षम होना चाहिए:
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
append 5
append 10
append 15
r <- sumST
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runState myMain
मैंने सोचा था कि इकाई ट्रांसफार्मर की बात की गई थी इसलिए मैं अपने राज्य इकाई के संचालन में एक समारोह में निष्पादित कर सकते हैं (ऊपर) और में आईओ संचालन उठा वह समारोह यह सब सेट करने का सही तरीका क्या है ताकि मैं संकेतों की परतों में से एक को हटा सकूं?
डैनियल समाधान (जो मैं समाधान चिह्नित कर दिया है) के अलावा, मैं भी कुछ विविधताएं स्थिति पर कुछ प्रकाश डाला सकता है मिल गया है। सबसे पहले, myMain के अंतिम कार्यान्वयन और मुख्य:
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
append 5
append 10
append 15
res <- sumST
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runStateT myMain new
अब, डैनियल को संलग्न और sumST के विभिन्न कार्यान्वयन, इसके अलावा में:
append :: Integer -> AppState()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: AppState Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
और (ध्यान दें कि केवल प्रकार घोषणा परिवर्तन, वास्तव में आप प्रकार घोषणा पूरी तरह से छोड़ सकते हैं!)
append :: MonadState ST m => Integer -> m()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: MonadState ST m => m Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
यह मेरे लिए हुआ है कि AppState/StateT इकाई नहीं रूप में ही है मूल राज्य मोनड, और मैं समस्त दोनों कोडिंग और राज्य मोनड के लिए संलग्न था। एक अर्थ में, उन्हें राज्य टी मोनैड में भी उठाया जाना था, हालांकि इनके बारे में सोचने का सही तरीका यह है कि उन्हें मोनड में रन होना चाहिए (इसलिए, runState script new
)।
मुझे यकीन नहीं है कि मैं इसे पूरी तरह से प्राप्त करता हूं, लेकिन मैं थोड़ी देर के लिए इसके साथ काम करूंगा, मोनाडस्टेट कोड पढ़ूंगा, और इसके बारे में कुछ लिखूंगा जब यह अंततः मेरे सिर में काम करता है।
आह, 'राज्य' मुझे लगता है की तुलना में अधिक बहुलक है, क्योंकि मेरे पास यह किसी कारण से मेरे सिर में था कि यह कार्य किसी राज्य के कन्स्ट्रक्टर को निर्यात करने के लिए क्षमा नहीं था। टीआईएल! –