Haskell 遅延評価と即時評価
必要になるまで評価されない、という遅延評価の理解だけでは、
一見、以下の実行例は不可解。
Prelude> :m Control.Monad
Prelude Control.Monad> liftM3 maybe (fail "$$$$") (return id) (return (Just 3.14))
*** Exception: user error ($$$$)
Prelude> :m Control.Applicative
Prelude Control.Applicative> maybe <$> (fail "$$$$") <*> (return id) <*> (return (Just 3.14))
*** Exception: user error ($$$$)
Prelude Control.Monad> liftM3 maybe (fail "$$$$") (return id) (return (Just 3.14))
*** Exception: user error ($$$$)
Prelude> :m Control.Applicative
Prelude Control.Applicative> maybe <$> (fail "$$$$") <*> (return id) <*> (return (Just 3.14))
*** Exception: user error ($$$$)
liftM3 の実装を見て謎が解けた。
liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
なるほどね。