从 `Rand StdGen X` 中提取 `X`

Extracting `X` from `Rand StdGen X`

2013 年 Yorgey 教授的 UPenn class 作业 12,它呈现 Battlefield 数据类型。

type Army = Int

data Battlefield = Battlefield { attackers :: Army, defenders :: Army } deriving Show

作业二题,要求实现randomrandomR功能

    -- @author: Brent Yorgey
    first :: (a -> b) -> (a, c) -> (b, c)
    first f (a, c) = (f a, c)

instance Random Battlefield where
    random = first (\(as, ds) -> Battlefield as ds) . twoInts
    randomR = undefined -- TODO

我使用以下函数实现了上述 random

randomBF :: Rand StdGen Battlefield
randomBF = getRandom

twoInts :: RandomGen g => g -> ((Army, Army), g)
twoInts gen = let (one, gen')  = random gen
                  (two, gen'') = random gen'
              in ((abs one, abs two), gen'')

我很好奇如何从 randomBF 获得 Battlefield

我尝试了以下方法:

ghci> evalRandT randomBF (mkStdGen 5)
Identity (Battlefield {attackers = 7777369639206507645, defenders = 5955775402155530247})

但是它被包裹在 Identity 中。我不确定那是什么。但是,如何提取惯用 Haskell 中的 Battlefield ... 部分?

要从 Identity monad 中提取值,请使用 runIdentity from Data.Functor.Identity

您还可以使用:evalRand randomBF (mkStdGen 5) 其中 returns 战场值。