A pris ma première fissure chez Monad Transformers. J'ai écrit un algorithme génétique simple pour ce que ma classe appelle le problème de «localisation de l'installation». L'algorithme n'est pas si important. J'ai généralement suivi le format expliqué dans ce chapitre de Real World Haskell.Appel de la fonction monadique à l'intérieur de la pile du transformateur
Ma pile de transformateur ressemble à ceci
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
Plus tard dans mon code, je définir ma principale action « étape » pour l'exécution d'un tour de l'accouplement et de survivre. Dans mon action, je n'ai aucun problème à générer un nombre aléatoire et à l'utiliser. Cependant, je voudrais déplacer le caractère aléatoire d'une fonction particulière hors de l'action d'étape et dans cette fonction. Malheureusement, je reçois des erreurs de type, et j'ai besoin d'une formation sur les deux pourquoi cela ne fonctionne pas, et comment faire fonctionner ce travail.
Vous avez probablement ne pas vraiment besoin de cela, mais ma fonction mate points seulement deux vecteurs ensemble:
mate :: CustomerService -> CustomerService -> Int -> CustomerService
mate a b split = (fst $ V.splitAt split a) V.++ (snd $ V.splitAt split b)
Alors, cela fonctionne:
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 [email protected](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
mais je vraiment définir plutôt la progéniture comme donc:
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)
Cependant quand j'essaye d'appeler cette fonction dans mon action d'étape avec quelque chose comme
(c1,c2) <- offspring p1 p2
Le compilateur me crie dessus ce type Rand ne me que je suppose que le type FacilityApp correspond pas à attendre ... est logique, mais je ne sais pas comment faire ce travail pour moi.
Je pense que peut-être cela a besoin d'un certain type de levage et de retour? Mais je ne peux pas le comprendre. Quelqu'un peut-il me parler du problème ici?
En tant que question secondaire, notez que j'utilise l'étatT pour tenir mon compteur rond. C'est plus rapide que d'ajouter un argument à l'étape. Existe-t-il un moyen encore plus efficace de prendre soin de cela?