Un'irritazione con lazy IO catturato la mia attenzione di recenteFMAP Strict utilizzando solo Functor, non Monade
import System.IO
import Control.Applicative
main = withFile "test.txt" ReadMode getLines >>= mapM_ putStrLn
where getLines h = lines <$> hGetContents h
causa pigro IO, il programma stampa sopra nulla. Quindi ho immaginato che questo potesse essere risolto con una versione rigorosa di fmap
. E in effetti, sono venuto su con solo un tale combinatore:
forceM :: Monad m => m a -> m a
forceM m = do v <- m; return $! v
(<$!>) :: Monad m => (a -> b) -> m a -> m b
f <$!> m = liftM f (forceM m)
Sostituzione <$>
con <$!>
fa davvero alleviare il problema. Tuttavia, non sono soddisfatto. <$!>
ha un vincolo Monad
, che sembra troppo stretto; è compagno <$>
richiede solo Functor
.
C'è un modo per scrivere <$!>
senza il vincolo Monad
? Se sì, come? Se no, perché no? Ho provato a gettare severità in tutto il luogo, senza alcun risultato (codice seguente non lavoro come desiderato):
forceF :: Functor f => f a -> f a
forceF m = fmap (\x -> seq x x) $! m
(<$!>) :: Functor f => (a -> b) -> f a -> f b
f <$!> m = fmap (f $!) $! (forceF $! m)
"(\ x -> seq x x)" è esattamente 'id', quindi non aiuta. –
Mi sembra una definizione molto strana di <$!>. Vorrei andare con "f <$!> m = forceM (liftM f m)" invece. Questo risolve anche il tuo problema, e sembra molto più sensato in altri contesti. Sospetto che non si possa definire questo per i funtori, però. – lpsmith