2017-10-11 4 views
2

J'ai récemment tombé sur loeb et moeb fonctions here et j'essaie d'explorer ce qu'il peut faire. J'essaie d'obtenir un comportement de type tableur avec la possibilité d'effectuer IO dans certaines "cellules". Je pensais que moeb traverse semblait être un bon candidat, mais toute fonction non triviale (c'est-à-dire autre que const $ return something) dans la liste que j'ai utilisée a causé l'appel entier pour toujours. Après cela, j'essayé de le tester dans State monade:moeb traverse non-terminaison

moeb f x = fix $ \g -> f ($g) x 

foo v = do 
    x <- get 
    vs <- v 
    put (x + 3) 
    return (x + (vs!!0)) 

test = [ 
    const $ return 7, 
    foo, 
    fmap length 
] 

main = print $ runState (moeb traverse test) 5 

Le résultat était la suivante:

([7,12,3],moeb.hs: out of memory 

Pourquoi cela? foo obtient et définit l'état, mais il évalue bien, tandis que l'évaluation de l'état final se bloque. Et comment puis-je obtenir un comportement de feuille de calcul avec E/S qui se termine?

Répondre

1

moeb traverse test :: State Int [Int] est une action pour produire une liste d'entiers.

Si vous dépliez la définition de moeb, vous obtenez

moeb traverse test 
    = traverse ($ moeb traverse test) test 

ce qui signifie que chaque élément f la feuille de calcul est passé l'action moeb traverse test à exécuter, à partir de zéro, au lieu d'utiliser le résultat de l'action récursivement.

Généraliser moeb en utilisant mfix pourrait aider mais je doute que le résultat en vaille la peine.

+0

Ok, je vois pourquoi ça se bloque, mais que voulez-vous dire en généralisant 'moeb' en utilisant' mfix'? – Ryba

+0

Un simple serait 'moebM f x = mfix $ \ g -> f ($ g) x'. Utilisez 'traverse' comme premier argument, mais' test' devra changer de type. –

+0

Cela a fonctionné, merci – Ryba