将Rand monad从`data`结构中带出来?

时间:2013-07-07 08:19:32

标签: haskell monads

我正在使用Control.Monad.Rand,我有一个结构

data MCSystem = MCSystem { params :: Params
                         , path   :: Path   }

功能,我不知道如何实现 -

runSystem :: (RandomGen g) => MCSystem -> Rand g MCSystem
runSystem system = MCSystem mcparams newPath -- this line doesn't make any
                                             --   sense and i know it
  where
    mcparams = params system
    newPath  = runPath $ path system

runPath :: (RandomGen g) => Path -> Rand g Path
-- basically performs a random mutation on the path

runPath会返回一个Rand g Path monad ...如何将其设为新的Rand g MCSystem monad,以便runSystem可以正确返回它,并且可以调用它后来用发电机?

我想也许我可以将所有内容重构为Reader monad,但我觉得如果可能的话我想避免它。

1 个答案:

答案 0 :(得分:3)

Rand是Monad的一个实例,可以用于monad的所有方式。就像任何其他monad一样,你“获得价值”,并使用>>=对其进行操作。

例如,这适用于runSystem的定义:

runSystem system = runPath (path system) >>= \newPath -> return (MCSystem (params system) newPath)

do语法使它更好:

runSystem system = do 
  newPath <- runPath (path system)
  return $ MCSystem (params system) newPath

使用Rand应用实例的最佳方式:

runSystem system = MCSystem <$> pure (params system) <*> runPath (path system)

但是,如果您还没有了解申请类,那可能没有多大意义(如果是这样的话,其他解决方案也没有问题)。

编辑:实际上,你真正需要的是Functor类型类,所以这也有效,并且是你能得到的最好的:

runSystem system = MCSystem (params system) <$> runPath (path system)

基本上,您将runPath (path system)的结果包裹在MCSystem

附近