Как создать MonadRandom (StateT PureMT m0)? (Хаскелл)

Я пытаюсь использовать MonadRandom из https://hackage.haskell.org/package/random-fu-0.2.6.0/docs/Data-Random.html#g:6

В частности, у меня есть функция с сигнатурой типа:

randomN :: MonadRandom m => m Int

и я хочу запустить его, используя Mersenne Twister с известным начальным числом.

Как мне «создать» экземпляр Monad m0 => MonadRandom (StateT PureMT m0) из документации?


person yong    schedule 19.08.2014    source источник


Ответы (2)


Поскольку экземпляр для MonadRandom уже существует для Monad m => StateT PureMT m, вам просто нужно что-то вроде

-- State s a = StateT s Identity a
test :: State PureMT (Int, Int)
test = do
    a <- randomN
    b <- randomN
    return (a, b)

И вы можете запустить его как

main :: IO ()
main = do
    -- You can replace 1234 with whatever seed you want
    let (result, finalState) = runState test $ pureMT 1234
    putStr "The result: "
    print result
    putStr "The final state: "
    print finalState
person bheklilr    schedule 19.08.2014

Хорошо, я понял, как решить мою проблему.

Поскольку документация для MonadRandom утверждает, что StateT PureMT m0 можно рассматривать как MonadRandom, мы можем «притвориться», что randomN на самом деле возвращает StateT PureMT m0. Мы выберем m0 в качестве идентификационной монады, другими словами, мы можем действовать так, как будто randomN имеет сигнатуру

randomN :: StateT PureMT Identity Int

Теперь, чтобы вернуть значение, мы просто разворачиваем: runIdentity (evalStateT (randomN) $ pureMT seed)

person yong    schedule 19.08.2014
comment
На самом деле мы не делаем вид, что randomN возвращает StateT PureMT m0 Int, потому что на самом деле это в этом контексте. Это все равно, что сказать, что мы должны притворяться, что f :: Num a => a -> a; f x = x + 1 возвращает Int при вызове f (1 :: Int). Класс типов конкретизируется, когда ему предоставляется конкретный тип для работы. - person bheklilr; 19.08.2014