Freeモナド実用の旅(1): ループからのBreak
とても簡単。Free(T)に「続きがない」ということを表すFunctorをはめるだけ。
ex1はある文字列を入力すると終了するプログラム。
import Prelude hiding (break) import Control.Monad.Trans.Free import Control.Monad.Trans import Control.Monad data Zero a = Zero deriving (Show, Eq, Ord) instance Functor Zero where fmap _ _ = Zero type BreakT = FreeT Zero break :: Monad m => BreakT m () break = liftF Zero runBreakT :: Monad m => BreakT m a -> m (Maybe a) runBreakT m = runFreeT m >>= \r -> case r of Pure a -> return (Just a) Free Zero -> return Nothing ex1 :: Int -> BreakT IO () ex1 n = do lift $ putStr "Can you break me? :" str <- lift getLine when (product (map fromEnum str) == 1383527552) $ lift (putStrLn "Exactly!") >> break ex1 (succ n) main = runBreakT (ex1 0)