2006-10-12 [長年日記]

[Haskell] 繰り返しとか

あるリストから最初に'x'が現れるまでのリストを取得するには、

h :: [Char]
h = takeWhile (/='x') ['a'..]

しますが、これをこのままIOにして、

h' :: IO [Char]
h' = takeWhile (/='x') `liftM` mapM (\_ -> getChar) (cycle [1])

とすると、当然ですが、終わらなくなります。

f :: IO [Char]
f = reverse `liftM` f' []
 where
     f' p = do c <- getChar
               if c == 'x' then return p else f' $ c:p

のように自前で再帰するか、再帰部分をunfoldMとして外に出して、

g :: IO [Char]
g = unfoldM g' 0
 where
     g' _ = do c <- getChar
               return $ if c == 'x' then Nothing else Just (c, 0)

unfoldM :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a]
unfoldM f x = do v <- f x
                 case v of
                     Just (a, b) -> unfoldM f b >>= return . (a:)
                     Nothing     -> return []

のようにすれば良いのですが、もう少しシンプルにできる方法はないものでしょうか。


トップ «前の日記(2006-10-11) 最新 次の日記(2006-10-13)»