我正在尝试了解以下类型签名的含义。
f :: Int -> Rand StdGen Int
所以Rand
是newtype
,source说。
-- | A basic random monad.
newtype Rand g a = Rand (RandT g Identity a)
deriving (Functor, Monad, MonadRandom, MonadSplit g)
我不知道右手边涉及什么,但让我继续。
它的种类是:
ghci> :k Rand
Rand :: * -> * -> *
我认为StdGen
是RandomGen
的一个实例,它是一个类型类。
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
。
答案 0 :(得分:2)
假设m
是Rand 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)