2011-02-11 5 views
7

J'ai un algorithme qui fonctionne sur un IntMap que je pense que le mieux serait exprimé impérativement. C'est-à-dire, je voudrais dire des choses comme:Existe-t-il une instance de monad pour Data.Map/Data.IntMap?

  • Recherchez la valeur X dans la carte.
  • S'il correspond à un critère, supprimez cette valeur de la carte.
  • Boucle jusqu'à ce qu'il n'y ait plus de valeurs dans la carte.

Ce serait assez trivial d'exprimer une récursion deux lignes, mais l'algorithme réel est un peu plus complexe, impliquant plusieurs suppressions et les recherches, donc je voudrais pouvoir exprimer en notation do .

Y at-il une norme « État » -comme monade où l'Etat est représenté par Data.Map ou Data.IntMap, où je peux faire quelque chose comme:

do 
    insert 5 20 
    (ma, mv) <- lookup 4 
    case mv of 
    Just v -> delete (fromJust ma) 
    Nothing -> return() 

Honnêtement, je ne suis pas sûr de savoir comment mieux exprimer cela. En raison de lookup il semblerait bénéficier d'une sorte de MaybeT IntMap m pile ou quelque chose.

J'ai fait un peu de travail à essayer de définir ma propre monade de l'Etat basé sur Data.IntMap, même obtenu jusqu'à faire insert et delete travail, mais nous avons eu un peu coincé avec la façon de traiter lookup. La plupart du temps je pense que c'est probablement quelque chose que quelqu'un a déjà résolu, mais je ne peux pas le trouver sur Hackage.

Répondre

21

Y a-t-il une raison particulière pour laquelle vous voulez éviter d'utiliser des transformateurs monad? si vous obtenez le paquet MaybeT de Hackage vous pouvez obtenir ce que vous voulez comme ceci:

import Control.Monad 
import Control.Monad.Maybe 
import Control.Monad.State 
import qualified Data.Map as Map 

type MapM k v a = MaybeT (State (Map.Map k v)) a 

lookupM k = MaybeT $ Map.lookup k `liftM` get 
insertM k = modify . Map.insert k 
deleteM k = modify $ Map.delete k 

runMap m = (flip execState) m . runMaybeT 

foo = runMap Map.empty $ do 
    insertM 5 20 
    v <- lookupM 4 
    deleteM v 

Lorsque lookupM échoue le reste du calcul échoue. Vous pouvez entrer et échapper à ces monades à tout moment afin de pouvoir les cacher sous une interface de fonction pure, c'est seulement la monade IO que vous ne voulez pas échapper sauf dans main (et en utilisant des fonctions dangereuses).

Tout ce dont vous avez besoin de vous souvenir est n'importe quelle action d'état qui retourne Peut-être que le type vient de se lever dans le constructeur de MaybeT. Si vous voulez faire des E/S, changez d'état en StateT.

+0

Wow. Je vous remercie. J'ai vraiment besoin de m'habituer à utiliser des transformateurs. Cet exemple est d'une grande aide pour montrer comment les utiliser pratiquement. Tous les didacticiels de la monade vous montrent comment en créer un à partir de rien, mais ils vous montrent rarement comment tirer parti de ce qui est déjà disponible. – Steve

+1

@Steve Ce qui m'a aidé à comprendre les transformateurs monad est de les considérer comme une pile de monades ou d'oignons avec des calques et les champs d'enregistrement ou les fonctions d'exécution de chaque type de transformateur monad. –

Questions connexes