Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “有条件”的较短方式;返回()”;在哈斯凯尔的单子链中(>;>;,>;=)?_Haskell - Fatal编程技术网

Haskell “有条件”的较短方式;返回()”;在哈斯凯尔的单子链中(>;>;,>;=)?

Haskell “有条件”的较短方式;返回()”;在哈斯凯尔的单子链中(>;>;,>;=)?,haskell,Haskell,我有一个简单的代码,它读取一个字符串并无限期地打印它 main :: IO () main = getLine >>= putStrLn >> main 现在,如果行是“退出”或“退出”,我想在调用getLine后退出 我的尝试: main :: IO () main = do line <- getLine if line == "exit" || line == "quit" then return () else putStrLn line

我有一个简单的代码,它读取一个字符串并无限期地打印它

main :: IO ()
main = getLine >>= putStrLn >> main
现在,如果行是“退出”或“退出”,我想在调用
getLine
后退出

我的尝试:

main :: IO ()
main = do
  line <- getLine
  if line == "exit" || line == "quit"
  then return ()
  else putStrLn line >> main
main::IO()
main=do
行>主

在我看来并不习惯。有更好的方法吗?

控制.Monad。除非
(这是比较流行的一种方法,
时)将此模式从代码中提取出来:

import Control.Monad (unless)

main = do
  line <- getLine
  unless (line == "exit" || line == "quit") $ do
    putStrLn line
    main
  -- or
  when (line /= "exit" && line /= "quit") $ do
    putStrLn line
    main
import Control.Monad(除非)
main=do

line由于使用if/else和do符号,您似乎关心代码的顺序感觉。您可以尝试以下方法:

main = getLine >>= proc
  where
    proc s | s == "exit" || s == "quit" = return ()
           | otherwise = putStrLn s >> main

追求时尚:

module Main where

import Control.Monad
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Class
import System.IO

isValid s = s ≠ "quit" && s ≠ "exit"

getL ∷ MaybeT IO String
getL = do s ← lift getLine
          guard (isValid s)
          return s


main = runMaybeT main' where
  main' = do
      lift $ putStr "Enter line: "
      lift $ hFlush stdout
      s ← getL
      lift $ putStrLn $  "Your line is: " ⧺ s
      main'

使用
管道-4.0

import Pipes
import qualified Pipes.Prelude as P

main = runEffect $
    P.stdinLn >-> P.takeWhile (`notElem` ["quit", "exit"]) >-> P.stdoutLn

我们可以创建一个助手函数,该函数在返回值时重复给定的操作:

import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Maybe

while :: (Monad m) => MaybeT m b -> m ()
while k = runMaybeT (forever k) >> return ()
一旦
k
返回
mzero
,循环停止。然后我们可以使用标准的
MonadPlus
combinator在任何地方很好地中断循环:

main = while $ do
        l <- lift getLine
        guard $ l /= "quit"
        lift $ putStrLn l

更新:也许最简单的解决方案是使用来自monad循环:


您可以在
Control.Monad
main=interact$unlines中的
时尝试
。takeWhile(/=“退出”)。行
不使用
翻转
翻转函数是一种有趣的方式!
main = while $ mfilter (/= "quit") (lift getLine) >>= lift . putStrLn
isValid s | s /= "quit"   = Just s
          | otherwise     = Nothing

main = whileJust_ (isValid `liftM` getLine) putStrLn