循环一元谓词

Pro*_*sch 3 monads haskell predicate

对于循环函数直到谓词成立有

until :: (a -> Bool) -> (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)

然而,一旦谓词具有以下形式,这就不够了

Monad m => (a -> m b)
Run Code Online (Sandbox Code Playgroud)

我发现的唯一方法是通过显式递归,例如从句柄读取直到EOF达到:

  (_, (Just stdout), _, _) <- createProcess (proc "task" (args fl)){ std_out = CreatePipe }
  let readH :: IO [Either String Task] -> IO [Either String Task]
      readH l = do eof <- hIsEOF stdout
                   if eof
                     then l
                     else do line <- hGetLine stdout
                             l' <- l
                             readH.return $ (eitherDecodeStrict' line) : l'
  out <- readH $ return []
Run Code Online (Sandbox Code Playgroud)

是否有更高阶的函数可以简化这个过程?也许与顺序一起?

Chr*_*lor 5

例如,您可以自己定义一个“monadic Until”函数

untilM :: Monad m => (a -> m Bool) -> (a -> m a) -> a -> m a
untilM p f = go
  where
    go x = do r <- p x
              if r
                then return x
                else do a <- f x
                        go a
Run Code Online (Sandbox Code Playgroud)

或者也许,如果你的谓词不需要参数,

untilM :: Monad m => m Bool -> (a -> m a) -> a -> m a
untilM p f = go
  where
    go x = do r <- p
              if r
                then return x
                else do a <- f x
                        go a
Run Code Online (Sandbox Code Playgroud)

或者甚至,你根本不想有任何争论,

untilM :: Monad m => m Bool -> m a -> m ()
untilM p f = do r <- p
                if r
                  then return ()
                  else do f
                          untilM p f
Run Code Online (Sandbox Code Playgroud)