Hãy bắt đầu ngay từ đầu:
type Rand a = State StdGen a
Dòng này nói với bạn rằng Rand a
là một loại từ đồng nghĩa với một loại State
, mà nhà nước được đưa ra bởi StdGen
và có giá trị cuối cùng là loại a
. Điều này sẽ được sử dụng để lưu trữ trạng thái của trình tạo số ngẫu nhiên giữa mỗi yêu cầu cho một số ngẫu nhiên.
Mã cho getRandom
có thể được chuyển đổi thành ký hiệu làm:
getRandom :: (Random a) => Rand a
getRandom = do
r <- get -- get the current state of the generator
let (a,g) = random r in do -- call the function random :: StdGen -> (a, StdGen)
put g -- store the new state of the generator
return a -- return the random number that was generated
Chức năng runRand
mất một hạt giống ban đầu n
và một giá trị r
loại Rand a
(trong đó, hãy nhớ rằng, chỉ là một từ đồng nghĩa với State StdGen a
). Nó tạo ra một máy phát điện mới với mkStdGen n
và cấp phát cho evalState r
. Hàm evalState
chỉ đánh giá giá trị trả về của loại State s a
, bỏ qua trạng thái.
Một lần nữa, chúng ta có thể chuyển đổi runRandIO
vào do
ký hiệu:
runRandIO :: Rand a -> IO a
runRandIO r = do
rnd <- randomIO -- generate a new random number using randomIO
return (runRand rnd r) -- use that number as the initial seed for runRand
Cuối cùng, getRandoms
mất một số n
đại diện cho số các giá trị ngẫu nhiên mà bạn muốn tạo ra. Nó tạo danh sách [1..n]
và áp dụng getRandom
vào danh sách. Lưu ý rằng các giá trị thực tế trong [1..n]
không được sử dụng (bạn có thể biết vì hàm lambda bắt đầu bằng \_ -> ...
). Danh sách chỉ ở đó để có thứ gì đó với số lượng phần tử chính xác. Vì getRandom
trả về một giá trị monadic, chúng tôi sử dụng mapM
để lập bản đồ trong danh sách, khiến trạng thái (ví dụ: StdGen
) được luồn chính xác qua từng cuộc gọi đến getRandom
.
Nguồn
2012-06-15 09:14:24