![](/img/trans.png)
[英]Function that runs a state monadic computation in the instrumented state monad
[英]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
也有run
, eval
和exec
變體,因為它實際上也是一個狀態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
正是我們所期望的:產生Bool
的IO
。 運行幾次:
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.