Cuối cùng tôi đã có một giữ về cách sử dụng monads (không biết nếu tôi hiểu họ ...), nhưng mã của tôi là không bao giờ rất thanh lịch. Tôi đoán là từ một thiếu hiểu về cách tất cả các chức năng trên Control.Monad
thực sự có thể giúp đỡ. Vì vậy, tôi nghĩ rằng nó sẽ là tốt đẹp để yêu cầu cho lời khuyên về điều này trong một đoạn mã cụ thể bằng cách sử dụng monad nhà nước.Lời khuyên cho mã thanh lịch hơn với monads?
Mục đích của mã là tính toán nhiều loại lượt đi ngẫu nhiên và đó là điều tôi đang cố gắng làm trước một điều phức tạp hơn. Vấn đề là tôi có hai phép tính stateful cùng một lúc, và tôi muốn biết làm thế nào để soạn chúng với sự sang trọng:
- các chức năng đó cập nhật các bộ tạo số ngẫu nhiên là một cái gì đó kiểu
Seed -> (DeltaPosition, Seed)
- Chức năng cập nhật vị trí của khung tập đi ngẫu nhiên là loại
DeltaPosition -> Position -> (Log, Position)
(trong đóLog
chỉ là một số cách để tôi báo cáo vị trí hiện tại của người đi bộ ngẫu nhiên là gì).
Những gì tôi đã làm điều này là:
Tôi có một chức năng để soạn này hai tính stateful:
composing :: (g -> (b, g)) -> (b -> s -> (v,s)) -> (s,g) -> (v, (s, g))
composing generate update (st1, gen1) = let (rnd, gen2) = generate gen1
(val, st2) = update rnd st1
in (val, (st2, gen2))
và sau đó tôi biến nó thành một chức năng soạn trạng thái:
stateComposed :: State g b -> (b -> State s v) -> State (s,g) v
stateComposed rndmizer updater = let generate = runState rndmizer
update x = runState $ updater x
in State $ composing generate update
Và sau đó tôi có điều đơn giản nhất, ví dụ: trình đi bộ ngẫu nhiên sẽ chỉ tổng hợp một số ngẫu nhiên vào vị trí hiện tại của nó:
update :: Double -> State Double Double
update x = State (\y -> let z = x+y
in (z,z))
generate :: State StdGen Double
generate = State random
rolling1 = stateComposed generate update
và một chức năng để làm điều này lặp đi lặp lại:
rollingN 1 = liftM (:[]) rolling1
rollingN n = liftM2 (:) rolling1 rollings
where rollings = rollingN (n-1)
Và sau đó, nếu tôi tải này trong ghci
và chạy:
*Main> evalState (rollingN 5) (0,mkStdGen 0)
[0.9872770354820595,0.9882724161698186,1.9620425108498993,2.0923229488759123,2.296045158010918]
tôi nhận được những gì tôi muốn, mà là một danh sách các vị trí bị người đi bộ ngẫu nhiên chiếm đóng. Nhưng ... tôi cảm thấy phải có một cách thanh lịch hơn để làm điều này. Tôi có hai câu hỏi:
Tôi có thể viết lại các chức năng đó theo cách "đơn thuần" hơn, sử dụng các chức năng thông minh từ
Control.Monad
?Có một mô hình chung về việc kết hợp các trạng thái như thế này có thể được sử dụng không? Điều này có liên quan gì đến máy biến áp đơn nguyên hay thứ gì đó như thế không?
Bằng cách này, bạn nên tránh sử dụng hàm tạo dữ liệu 'State', vì kế thừa' mtl' ('monads-fd'),' State' được định nghĩa theo 'StateT' và do đó hàm tạo dữ liệu' State' không tồn tại. –
@TravisBrown Trên thực tế, 'monads-fd' không được hỗ trợ cho' mtl'. (Nhận ra rằng bình luận của bạn là 5 tuổi.) – crockeea