0

我正在使用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单子......我如何拉它来制作一个新的Rand g MCSystem单子,以便runSystem可以正确返回它,并且可以稍后用生成器调用它?

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

4

1 回答 1

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

于 2013-07-07T08:32:28.750 回答