簡體   English   中英

使用狀態和隨機性概念運行此monadic計算

[英]Run this monadic computation with notion of state and randomness

我描述了以下計算:

import Control.Monad.State
import Control.Monad.Identity
import Control.Monad.Random.Class

-- * fair coin
fair :: MonadRandom m => m Bool
fair = (\p -> p <= 0.5) <$> getRandomR (0,1 :: Double)

-- * how do i run this 
bar :: (MonadState Bool m, MonadRandom m) => m Bool
bar = fair >>= \b -> put b >> return b

而且我想知道如何運行bar以便在期望中, bar評估為True一半時間。

簡而言之:

evalRandIO $ evalStateT bar False

讓我們分開吧。 bar需要能夠將Bool維持為狀態,並能夠獲得隨機值。 我們可以用任何一種方式築巢; 在這里,我選擇將狀態分層隨機,但你可以反過來做。

evalStateT具有此類型簽名:

evalStateT :: Monad m => StateT s m a -> s -> m a

換句話說,如果某些東西需要一個狀態分層在其他monad之上,它會實現該狀態部分,並根據底層monad給出該動作。 名稱的eval部分意味着它將拋出結果狀態並僅為您提供值; 還有execStateT為您提供結果狀態並拋出輸出, runStateT為您提供兩者的元組。 我應該注意到,無論如何,我們必須給它一個初始狀態。 你的代碼不使用初始狀態,所以我們也可以使用undefined ,但是我使用了False

那么現在我們已經實現了狀態位,我們還剩下什么?

ghci> :t evalStateT bar False
evalStateT bar False :: MonadRandom m => m Bool

它想要一個可以給它隨機值的monad。 好吧,我們有其中一個。 Rand會這樣做。 Rand也有runevalexec變體,因為它實際上也是一個狀態monad; 它擁有一些RandomGen類的值。 在這里,我們希望在年底放棄狀態,我們希望保持的結果,也因此我們使用了run變種。 那么,我們現在有什么?

ghci> :t runRand (evalStateT bar False)
runRand (evalStateT bar False) :: RandomGen g => g -> (Bool, g)

為了比較:

ghci> :t random
random :: (RandomGen g, Random a) => g -> (a, g)

所以現在我們有一個普通的函數,它接受一個隨機數生成器狀態並吐出一對結果和一個新狀態,就像從System.Random random一樣。 我們怎么用呢? 好吧,通過System.Random模塊, getStdRandom看起來很有用:

getStdRandom :: (StdGen -> (a, StdGen)) -> IO a

它需要一個像我們所擁有的功能,並將其轉換為IO動作。 (這是有意義的,它將是IO ;它采取一些全局狀態(即標准隨機數生成器)並更新它。)在解決之后我們有什么?

ghci> :t getStdRandom . runRand $ evalStateT bar False
getStdRandom . runRand $ evalStateT bar False :: IO Bool

正是我們所期望的:產生BoolIO 運行幾次:

ghci> let barIO = getStdRandom . runRand $ evalStateT bar False
ghci> barIO
True
ghci> barIO
True
ghci> barIO
False

隨便給我一點。 然而, 正如卡斯滕在評論中提到的那樣 ,有一個更短的方式。 由於這是一個常見的用例, Control.Monad.Random模塊提供了一個快捷方式evalRandIO ,它本質上就是getStdRandom . runRand 我們上面getStdRandom . runRand 這是一個簡單的替代品

evalRandIO $ evalStateT bar False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM