Tôi ban đầu sẽ đăng bài này làm nhận xét nhưng đã quyết định giải thích thêm một chút.
Nói đúng, get
không "lấy" một đối số. Tôi nghĩ rất nhiều những gì đang diễn ra được che giấu bởi những gì bạn không nhìn thấy - các định nghĩa cá thể của nhà nước.
get
thực sự là một phương pháp của lớp MonadState. Các đơn nguyên nhà nước là một thể hiện của MonadState, cung cấp các định nghĩa sau đây của get
:
get = State $ \s -> (s,s)
Nói cách khác, get
chỉ trả về một đơn nguyên nhà nước rất cơ bản (ghi nhớ rằng một đơn nguyên có thể được coi như là một "wrapper" cho một tính toán), trong đó bất kỳ đầu vào s
vào tính toán sẽ trả về một cặp s
là kết quả.
Điều tiếp theo chúng ta cần phải nhìn vào là >>=
, mà Nhà nước định nghĩa thusly:
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
Vì vậy, >>=
sẽ mang lại một tính toán mới, trong đó sẽ không được tính cho đến khi nó nhận được một trạng thái ban đầu (điều này đúng với tất cả các tính toán của Nhà nước khi chúng ở dạng "bọc" của chúng). Kết quả của tính toán mới này đạt được bằng cách áp dụng bất cứ điều gì ở phía bên phải của >>=
đến kết quả của việc chạy tính toán ở bên trái.(Đó là một câu khá khó hiểu có thể yêu cầu thêm một hoặc hai lần đọc.)
Tôi thấy nó khá hữu ích để "desugar" mọi thứ đang diễn ra. Làm như vậy sẽ mất nhiều đánh máy hơn, nhưng nên trả lời câu hỏi của bạn (trong đó get
đang nhận được từ) rất rõ ràng. Lưu ý rằng những điều sau đây cần được xem xét psuedocode ...
test x =
State $ \s -> let
(a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get'
in runState (rightSide a) s'
where
rightSide test =
let test' = x ++ test in
State $ \s2 -> let
(a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put'
in runState (rightSide2 a2) s2'
rightSide2 _ =
-- etc...
Điều đó sẽ làm cho nó rõ ràng rằng kết quả cuối cùng của chức năng của chúng tôi là một tính toán nhà nước mới sẽ cần một giá trị ban đầu (s
) để làm cho phần còn lại của công cụ xảy ra. Bạn đã cung cấp s
làm "testtest"
với cuộc gọi runState
của mình. Nếu bạn thay thế "testtest" cho s
trong mã giả ở trên, bạn sẽ thấy rằng điều đầu tiên xảy ra là chúng tôi chạy get
với "testtest" làm 'trạng thái ban đầu'. Điều này mang lại ("testtest", "testtest")
và cứ tiếp tục như vậy.
Vì vậy, đó là nơi get
nhận trạng thái ban đầu của bạn "kiểm tra". Hi vọng điêu nay co ich!
Tôi không thể nghĩ ra một từ nào tốt hơn khi tôi nói "lấy" một cuộc tranh luận. Cảm ơn lời giải thích rất chi tiết này. – Rayne