Je dirais que la meilleure chose à demander n'est pas comment nous l'appellerions, mais comment nous analyserions un tel code. Et ma première question clé dans une telle analyse serait:
- L'effet secondaire dépend-il de l'argument de la fonction ou du résultat de l'effet secondaire?
- Non: la "fonction efficace" peut être reformulée en une fonction pure, une action efficace et un mécanisme permettant de les combiner.
- Oui: la "fonction efficace" est une fonction qui produit un résultat monadique.
Ceci est simple à illustrer dans Haskell (et cette phrase n’est qu’une demi-plaisanterie). Un exemple du cas "non" serait quelque chose comme ceci:
double :: Num a => a -> IO a
double x = do
putStrLn "I'm doubling some number"
return (x*2)
Dans cet exemple, l'action que nous effectuons (imprimer la ligne "I'm doubling some number"
) n'a aucun impact sur la relation entre x
et le résultat. Cela signifie que nous pouvons le refactoriser de cette manière (en utilisant la Applicative
classe et son *>
opérateur), ce qui montre que la fonction et l'effet sont en fait orthogonaux:
double :: Num a => a -> IO a
double x = action *> pure (function x)
where
-- The pure function
function x = x*2
-- The side effect
action = putStrLn "I'm doubling some number"
Donc, dans ce cas, je dirais personnellement que c'est un cas où vous pouvez factoriser une fonction pure. Cela concerne beaucoup de programmes Haskell - apprendre à décomposer les parties pures du code efficace.
Un exemple du type "oui", où les parties pures et effectives ne sont pas orthogonales:
double :: Num a => a -> IO a
double x = do
putStrLn ("I'm doubling the number " ++ show x)
return (x*2)
Maintenant, la chaîne que vous imprimez dépend de la valeur de x
. La partie fonction (multiplier x
par deux), cependant, ne dépend pas du tout de l'effet, nous pouvons donc la factoriser:
logged :: (a -> b) -> (a -> IO x) -> IO b
logged function logger a = do
logger a
return (function a)
double x = logged function logger
where function = (*2)
logger x putStrLn ("I'm doubling the number " ++ show x)
Je pourrais continuer à donner d’autres exemples, mais j’espère que c’est suffisant pour illustrer le point que j’avais commencé: vous n’appelez pas quelque chose, vous analysez la relation entre les parties pure et efficace et les factorisez quand c’est le cas. à votre avantage.
C'est l'une des raisons pour lesquelles Haskell utilise Monad
tellement sa classe. Les monades sont (entre autres) un outil pour effectuer ce type d’analyse et de refactorisation.