La fonction bind
(>>=
) a la signature:façon idiomatiques à mettre en œuvre "m (ta) -> (a -> m (tb)) -> m (tb)"
m a -> (a -> m b) -> m b
Cependant, je veulent une fonction avec la signature:
m (t a) -> (a -> m (t b)) -> m (t b)
Plus précisément, j'ai une fonction qui donne un nombre entier, elle retourne une liste d'entiers à l'intérieur d'un IO:
f :: Int -> IO [Int]
mais je souhaite l'appliquer à un IO of list of Integers
et je ne peux pas utiliser la fonction de liaison régulière car elle est enveloppée dans deux conteneurs, c'est-à-dire une liste contenue dans un IO. Searching on hoogle n'aide pas.
J'utilise l'approche suivante pour mettre en œuvre cette:
Supposons que la mise en œuvre de la fonction est:
f :: Int -> IO [Int]
f x = do
return $ [x-10, x+10]
J'utilise deux fonctions d'aide pour obtenir ce que je veux:
f' :: [Int] -> IO [Int]
f' xs = do
list <- traverse f xs
return $ join list
f'' :: IO [Int] -> IO [Int]
f'' xs = do
ys <- xs
f' ys
Ce qui précède fonctionne mais je voudrais savoir s'il existe une meilleure façon de l'implémenter en haskell?
Je suis ai pas la recherche d'une solution puisque je déjà. Je veux un moyen idiomatique de résoudre cela. – mandark
Je ne sais pas si vous avez déjà lu les réponses, mais * "Plus généralement, quelle est la fonction m1 m2 a -> (a -> m1 m2 b) -> m1 m2 b?" * Fait partie de cette question en double. La réponse: c'est impossible dans le cas général. Voir la deuxième réponse. – 4castle
Si vous supprimez les signatures de type sur 'f'' et' f''' et absentez 'f' dans un paramètre, vous obtiendrez le type le plus général déduit par le typechecker. Je dirais que ces implémentations sont idiomatiques, sauf peut-être l'utilisation de la notation 'do' au lieu de' >> = 'et' fmap' mais ce sont des problèmes purement stylistiques. En l'état, cette question est entièrement basée sur l'opinion - pouvez-vous clarifier ce que votre code n'est pas assez bon, c'est-à-dire ce que vous aimeriez voir accomplir? – user2407038