In qualche modo mistificato dal seguente codice. Nella versione non-giocattolo del problema sto provando a fare un calcolo monadico in un risultato monad, i cui valori possono essere costruiti solo dall'IO. Sembra che la magia dietro IO renda tali calcoli rigorosi, ma non riesco a capire come esattamente ciò accada.La monade IO impedisce il cortocircuito della mappaM incorporata?
Il codice:
data Result a = Result a | Failure deriving (Show)
instance Functor Result where
fmap f (Result a) = Result (f a)
fmap f Failure = Failure
instance Applicative Result where
pure = return
(<*>) = ap
instance Monad Result where
return = Result
Result a >>= f = f a
Failure >>= _ = Failure
compute :: Int -> Result Int
compute 3 = Failure
compute x = traceShow x $ Result x
compute2 :: Monad m => Int -> m (Result Int)
compute2 3 = return Failure
compute2 x = traceShow x $ return $ Result x
compute3 :: Monad m => Int -> m (Result Int)
compute3 = return . compute
main :: IO()
main = do
let results = mapM compute [1..5]
print $ results
results2 <- mapM compute2 [1..5]
print $ sequence results2
results3 <- mapM compute3 [1..5]
print $ sequence results3
let results2' = runIdentity $ mapM compute2 [1..5]
print $ sequence results2'
L'output:
1
2
Failure
1
2
4
5
Failure
1
2
Failure
1
2
Failure
Grazie mille per la risposta, chi. Posso chiederti come fai a sapere che la definizione IO di mapM è severa e che il ritorno è pigro? – NioBium
@NioBium 'Fallimento >> = f = Fallimento' scarta il' f': non è necessario procedere ulteriormente sulla catena monadica. IO ha una definizione di leva inferiore che non è facilmente scrivibile, ma - salvo eccezioni - 'action >> = f' chiamerà sempre' f' poiché ci si aspetta che ad es. 'action >> print 4' finirà per stampare 4 indipendentemente da cosa fa l'azione (escludendo eccezioni IO e non-terminazione). – chi
Giusto. Grazie ancora! – NioBium