Una irritación con IO perezoso cogió a mi atención recientementefmap estricto utilizando sólo Functor, no Mónada
import System.IO
import Control.Applicative
main = withFile "test.txt" ReadMode getLines >>= mapM_ putStrLn
where getLines h = lines <$> hGetContents h
Debido a la pereza IO, el programa imprime por encima de nada. Así que imaginé que esto podría resolverse con una versión estricta de fmap
. Y, de hecho, yo he venido para arriba con apenas un combinador tales:
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)
Sustitución <$>
con <$!>
en efecto aliviar el problema. Sin embargo, no estoy satisfecho. <$!>
tiene una restricción Monad
, que se siente demasiado apretada; es compañero <$>
requiere solo Functor
.
¿Hay una manera de escribir <$!>
sin la limitación Monad
? Si es así, ¿cómo? ¿Si no, porque no? He intentado tirar rigor por todo el lugar, sin ningún resultado (siguiente código no trabajo como se desee):
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)" es precisamente 'id', por lo que no ayuda. –
Esto me parece una definición muy extraña de <$!>. Me gustaría ir con "f <$!> m = forceM (liftM f m)" en su lugar. Esto también resuelve tu problema y parece mucho más sensato en otros contextos. Sin embargo, sospecho que no puedes definir esto para los funtores. – lpsmith