【发布时间】:2014-05-02 00:16:34
【问题描述】:
我在 Monad Transformers 中第一次尝试。为我的班级所说的“设施位置”问题编写了一个简单的遗传算法。算法不是那么重要。
我一般遵循Real World Haskell这一章解释的格式。
我的变压器堆栈看起来像这样
newtype FacilityApp a = MyA {
runA :: RandT StdGen ( ReaderT Environment ( StateT (Population, Int) IO)) a
} deriving (Monad, MonadIO, MonadReader Environment, MonadState (Population,Int), MonadRandom)
runFacility :: FacilityApp a -> Input -> StdGen -> IO a
runFacility k input g =
let env = mkEnv input defParms
(pop, g') = runRand (genInitialPopulation env) g
state = (pop, numRounds defParms)
ra = runA k
rr = runReaderT rrand env
rs = evalStateT rr state
rrand = evalRandT ra g'
in rs
稍后在我的代码中,我定义了运行一轮交配和生存的主要“步骤”动作。在我的步骤操作中,我可以毫不费力地生成一个随机数并使用它。但是,我想将特定函数的随机性从步进操作移到该函数中。不幸的是,我遇到了类型错误,并且需要一些关于为什么这不起作用以及如何使它起作用的教育。
你可能真的不需要这个,但我的 mate 函数只是将两个向量拼接在一起:
mate :: CustomerService -> CustomerService -> Int -> CustomerService
mate a b split = (fst $ V.splitAt split a) V.++ (snd $ V.splitAt split b)
所以,这行得通:
offspring' :: CustomerService -> CustomerService -> Int -> (CustomerService, CustomerService)
offspring' a b split = (mate a b split, mate b a split)
step :: FacilityApp [CustomerService]
step = do
(pop, n) <- get
env <- ask
let e = (warehouses env, customers env)
let sorted@(p1:p2:_) = sortBy (sortByCost e) $ filter (validSolution e) pop
let (_:_:rest) = reverse sorted
-- these next two lines are of my concern
split <- getRandomR (1, V.length p1)
let (c1,c2) = offspring' p1 p2 split
-- eventually put the new children in the state and step again
put (c1:c2:rest, (n-1))
if n > 0 then step else return pop
但我真的更愿意像这样定义后代:
offspring :: (RandomGen g) => CustomerService -> CustomerService -> Rand g (CustomerService, CustomerService)
offspring a b = do
split <- getRandomR (1, V.length a)
return (mate a b split, mate b a split)
但是,当我尝试在我的步骤操作中调用此函数时,类似于
(c1,c2) <- offspring p1 p2
编译器对我大喊 Rand 类型与预期的 FacilityApp 类型不匹配...我想这对我来说是有道理的,但我不知道如何让它为我工作。
我认为这可能需要某种类型的提升和返回?但我无法弄清楚。有人可以在这里指导我解决问题吗?
作为一个附带问题,请注意我正在使用 StateT 来固定我的圆形计数器。这比在 step 中添加参数要快。有没有更有效的方法来解决这个问题?
【问题讨论】:
标签: haskell monads monad-transformers