Haskell 仅使用函子而非单子的严格fmap
最近我注意到了一个对懒惰IO的恼怒Haskell 仅使用函子而非单子的严格fmap,haskell,monads,strictness,Haskell,Monads,Strictness,最近我注意到了一个对懒惰IO的恼怒 import System.IO import Control.Applicative main = withFile "test.txt" ReadMode getLines >>= mapM_ putStrLn where getLines h = lines <$> hGetContents h 用替换确实可以缓解问题。然而,我并不满意有一个Monad约束,感觉太紧了;它的同伴只需要Functor 有没有一种方法可以在没有
import System.IO
import Control.Applicative
main = withFile "test.txt" ReadMode getLines >>= mapM_ putStrLn
where getLines h = lines <$> hGetContents h
用
替换
确实可以缓解问题。然而,我并不满意
有一个Monad
约束,感觉太紧了;它的同伴
只需要Functor
有没有一种方法可以在没有单子约束的情况下编写
?若否,原因为何?我已经尝试过在所有地方施加严格的限制,但没有任何效果(以下代码不能按预期工作):
forceF::函子f=>fa->fa
forceF m=fmap(\x->seq x x)$!M
()::函子f=>(a->b)->f a->f b
f m=fmap(f$!)$!(力$!m)
我认为这是不可能的,而且一元forceM
也不适用于所有的单子:
module Force where
import Control.Monad.State.Lazy
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)
test :: Int
test = evalState (const 1 <$!> undefined) True
forceM
需要足够严格的(>>=)
来实际强制其参数的结果<代码>函子
甚至没有(>>=)
。我不知道怎样才能写出一个有效的forceF
。(当然,这并不能证明这是不可能的。)“(\x->seq x x x)”正是id
,所以这没有帮助。对我来说,这似乎是一个非常奇怪的定义。我会用“fm=forceM(liftM-fm)”来代替。这也解决了您的问题,在其他情况下似乎更明智。不过,我怀疑你不能为函子定义这个。
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)
module Force where
import Control.Monad.State.Lazy
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)
test :: Int
test = evalState (const 1 <$!> undefined) True
Prelude Force> test
1