建立一个Rand StdGen Int

时间:2015-01-23 04:35:26

标签: haskell

我正在尝试了解以下类型签名的含义。

f :: Int -> Rand StdGen Int

所以Randnewtypesource说。

-- | A basic random monad.
newtype Rand g a = Rand (RandT g Identity a)
    deriving (Functor, Monad, MonadRandom, MonadSplit g)

我不知道右手边涉及什么,但让我继续。

它的种类是:

ghci> :k Rand
Rand :: * -> * -> *

我认为StdGenRandomGen的一个实例,它是一个类型类。

docs注意:

data StdGen

The StdGen instance of RandomGen has a genRange of at least 30 bits.

修改: 根据{{​​3}}的评论,Rand StdGen Int是具体类型。

ghci> :k Rand StdGen Int
Rand StdGen Int :: *

但是,我不确定制作Rand StdGen Int意味着什么。

请提供上述功能的实施,f

2 个答案:

答案 0 :(得分:2)

假设mRand StdGen Int类型的值。然后我们可以做的一些事情是:

-- use it to generate a random Int
evalRandIO m >>= print   -- generate a random Int and print it

-- create a generator for a pair of random Ints
twoRandInts :: Rand StdGen (Int,Int)
twoRandInts = do a <- m; b <- m; return (a,b)

您可以将其视为(monadic)过程,使用StdGen种子创建随机Int。请注意,m本身就是程序。要“运行”该过程,您需要使用evalRandIO等函数。

要回答关于像f这样的函数的问题,请考虑这一点(取自MonadRandom文档的示例部分)(link)

-- produce a random number between 1 and n
f :: Int -> Rand StdGen Int
f n = getRandomR (1,n)

另一个例子:

-- produce a random multiple of n
g :: Int -> Rand StdGen Int
g n = fmap (*n) getRandom

要创建Rand g a值,请使用Control.Monad.Random.Class中定义的getRandom*方法。

答案 1 :(得分:1)

你需要一直跟着兔子洞。

newtype Rand g a = Rand (RandT g Identity a)

所以要构建Rand StdGen Int,您需要RandT StdGen Identity Int。然后(留下一些噪音):

newtype RandT g m a = RandT (StateT g m a)

因此对于 ,您需要StateT StdGen Identity Int。然后

newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}

所以你需要的是StdGen -> Identity (Int, StdGen)。现在因为

newtype Identity a = Identity {runIdentity :: a}

StdGen -> (Int, StdGen)基本相同。

所以Rand StdGen Int基本上是一个深层newtype围绕一个带StdGen的函数,产生Int结果和新StdGen

但是,您不能直接使用它来构建f,因为Control.Monad.Random 不会导出 newtype构造函数,因此这种表示形式对用户隐藏图书馆。相反,您需要使用 提供的API函数。一种可能性:

f :: Int -> Rand StdGen Int
f n = getRandomR (0,n)