J'ai des fonctions écrites en C que j'appelle de Haskell. Ces fonctions renvoient io (cint) code>. Parfois, je veux exécuter toutes les fonctions, peu importe ce que l'un d'entre eux reviendra, et c'est facile. Pour des mesures d'exemple, il s'agit de l'idée générale de ce qui se passe actuellement:
do {
result = function_with_side_effects(input_list[index++]);
} while (result == success && index < max_index);
5 Réponses :
EDIT: strong> Maintenant, je vois ce que vous cherchez. gbacon a posté une belle En réalité, étant donné que vous êtes seulement intéressé par les effets secondaires, Vous appelez cela comme: p> Réponse originale: strong> p> Vous ne pouvez pas simplement "bloquer" les valeurs du Le La fonction de levage prendra une fonction (comme une note latérale, vous pouvez trouver une fonction comme celle-ci en recherchant Pour son type sur howogle , dans ce cas en recherchant: avec Quel (code> Fonction code>, qui est presque la "primitive" dont vous avez besoin.
Quelque séquence _ code> devrait suffire. Voici une définition (encore une fois inspirée par Gbacon, votez-le!): P>
io code> monad pour une utilisation avec
TakeWile CODE>, mais vous pouvez "soulever"
Main-quel code> pour une utilisation dans une monade! p>
(A -> B) code> à un fonction
(ma -> mb) code>, où
m code> est une monade. p>
monad m => (a -> b) -> (MA -> MB) code>
) p> mapM f [0..1]
=
sequence (map f [0..1])
=
sequence (f 0 : map f [1..1])
=
sequence (f 0 : f 1 : [])
=
sequence ((print 0 >> return 0) : f 1 : [])
=
sequence ((print 0 >> return 0) : (print 1 >> return 1) : [])
=
do x <- (print 0 >> return 0)
xs <- (sequence ((print 1 >> return 1) : []))
return (x:xs)
=
do x <- (print 0 >> return 0)
xs <- (do y <- (print 1 >> return 1)
ys <- sequence ([])
return (y:ys))
return (x:xs)
=
do x <- (print 0 >> return 0)
xs <- (do y <- (print 1 >> return 1)
ys <- return []
return (y:ys))
return (x:xs)
=
do x <- (print 0 >> return 0)
xs <- (do y <- (print 1 >> return 1)
return (y:[]))
return (x:xs)
=
do x <- (print 0 >> return 0)
xs <- (print 1 >> return (1:[]))
return (x:xs)
=
do x <- (print 0 >> return 0)
print 1
return (x:1:[])
=
do print 0
print 1
return (0:1:[])
Ce n'était pas le vrai comportement que je voulais, mais +1 pour une bonne explication. Le liftm gagne beaucoup plus de sens maintenant.
Je ne pense pas qu'il y ait quelque chose comme un à prendre à prendre code> dans la bibliothèque standard, mais vous pouvez l'écrire vous-même de manière à ce que ce soit autant que nécessaire est exécuté:
*Main> takeWhileM (<4) (map f [1..5])
1
2
3
4
[1,2,3]
Pour la cohérence avec Control.monad.filterm code>, je m'attendrais à un type de type
TakewhtileM :: (Monad M) => (A -> M Bool) -> [A] -> m [a] code>; Cela rendrait l'utilisation quelque chose comme
rejoindre. Séquence de levage. Takewhilem (lifting (<4)) code>. Mais c'est un peu plus laidèque pour quel op veut, alors meh.
@sth, @ephemient: pas dans la bibliothèque standard, mais dans mon package "Générateur" nouvellement publié (en piratage), il y a une fonction de prime plus générale. Votre prise de maintien a besoin de la liste des actions pour ne pas dépendre des actions à l'intérieur de la monade, tandis que le générateur est victime d'une liste dont la monade est M, permettant la même chose et plus.
+1 pour correspondre exactement au comportement que je voulais. J'ai mis à jour la question et je vais attendre et voir si quelqu'un a une solution LIB standard. S'il n'y en a pas, j'accepte votre réponse.
Vous pouvez utiliser celui de "Liste" Package.
FromList [0..5] code> crée une liste monadique contenant 0..5 qui n'effectue aucune action monadique li>
fmap f code> à cette liste entraîne un
listt io (io int) code> qui n'active toujours aucune action monadique, contient simplement des utilisateurs. Li>
jointM code> tourne dans un
listt io int code>. Chaque action contenue serait exécutée lorsque l'élément est consommé et que son résultat sera la valeur de la liste. LI>
Main-quelconque code> est généralisé pour toute liste
code>. Les deux
[] code> et "
monad m => listt m code>" sont des instances de
Liste code>. Li>.
Exécuter code> consomme la liste monadique, exécutant toutes ses actions. Li>
"Tolist :: Liste m => MA -> Itemm m [a]" " code> ("
itemm (listt io) code> "est
io code>). Donc, dans ce cas, c'est "
tolist :: listt io a -> io [a] code>". Mieux encore, vous pouvez continuer à utiliser des fonctions supérieures telles que
scanl code>, etc. pour traiter la liste monadique telle qu'elle est exécutée. LI>
ul> p>
Vous pouvez définir séquence comme le problème avec en utilisant liftm2 code>
que vous avez vu est que vous n'avez pas l'occasion d'arrêter m2 code>, qui pourrait être
launchthemissiles code>! p>
gardien code>
comme dans ce qui suit semble attrayant: p> *Main> untilM (>= 4) as
1
2
3
4
+1, Nice définition de Quelques-séquences code>. J'essayais d'abord de le définir en utilisant
Foldm Code> au lieu de
Plier "/ code>, mais cela ne fonctionnera évidemment pas, car cela oblige toute la liste.
Quelqu'un a suggéré un meilleur nom: Séquencleontil. J'ai aussi ajouté Spanm comme alternative.
Plus récemment, vous pouvez utiliser le monadlist Hackage qui inclut Fonctions pratiques comme Takewhilem, DropwriLem, Deletebym et beaucoup plus. p>
Il est également un peu décevant que
sortby code> n'est pas défini en termes de
Sortbilym :: monad m => (a -> A -> m commande) -> [a] -> m [a ] code>.