最近私の注意を引いた怠惰なIOの1つの苛立ち
import System.IO
import Control.Applicative
main = withFile "test.txt" ReadMode getLines >>= mapM_ putStrLn
where getLines h = lines <$> hGetContents h
遅延 IO のため、上記のプログラムは何も出力しません。したがって、これは の厳密なバージョンで解決できると想像しましたfmap
。実際、私はちょうどそのようなコンビネータを思いつきました:
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)
に置き換える<$>
と、<$!>
実際に問題が軽減されます。しかし、私は満足していません。きつすぎると感じる制約があります<$!>
。Monad
それはコンパニオン<$>
のみを必要としFunctor
ます。
制約<$!>
なしで書く方法はありますか?Monad
もしそうなら、どのように?そうでない場合、なぜですか?私はあらゆる場所で厳格さを投げようとしましたが、役に立ちませんでした(次のコードは期待どおりに機能しません):
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)