J'ai une fonction comme ça

foo :: X -> Y -> Z

Et j'ai deux calculs séparés qui sont effectués pour obtenir mes variables de type X et Y, mais ils peuvent échouer, donc j'utilise un Maybe

calc1 :: A -> Maybe X
calc2 :: B -> Maybe Y

Maintenant, je ne sais pas comment utiliser les opérations de monade pour obtenir ce comportement souhaité

safe_foo :: Maybe X -> Maybe Y -> Maybe Z
safe_foo Nothing _ = Nothing
safe_foo _ Nothing = Nothing
safe_foo (Just x) (Just y) = Just (foo x y)

Quelle est la meilleure façon de procéder?

5
Abe 1 sept. 2020 à 18:09

2 réponses

Meilleure réponse

Il vous suffit de liftA2, qui est défini comme faisant partie de la classe de type Applicative.

safe_foo = liftA2 foo

Ou bien, dans le "style applicatif":

safe_foo mx my = foo <$> mx <*> my
5
Robin Zigmond 1 sept. 2020 à 15:18

Vous pouvez utiliser la monade avec un bloc do

safe_foo mx my = do    -- BTW, we underscore_case is unconventional in Haskell,
   x <- mx             -- preferrably use camelCase instead
   y <- my
   return $ foo x y

... ou, désucré et simplifié,

safe_foo mx my = mx >>= (<$>my) . foo

Mais vraiment vous n'avez pas besoin de Monad ici, Applicative suffit.

safe_foo = liftA2 foo

Ou directement en utilisant les fonctions calc,

   foo <$> calc1 a <*> calc2 b
5
leftaroundabout 1 sept. 2020 à 16:32