【问题标题】:Idiomatic way to conditionally process IO in Haskell在 Haskell 中有条件地处理 IO 的惯用方法
【发布时间】:2011-04-21 10:40:16
【问题描述】:

我正在用 Haskell 编写一个小 shell 脚本,它可以接受一个可选参数。但是,如果参数不存在,我想从标准输入中获取一行来请求一个值。

在 Haskell 中执行此操作的惯用方式是什么?

#!/usr/bin/env runhaskell

import Control.Applicative ((<$>))
import Data.Char (toLower)
import IO (hFlush, stdout)
import System.Environment (getArgs)

main :: IO ()
main = do args <- getArgs
          -- here should be some sort of branching logic that reads
          -- the prompt unless `length args == 1`
          name <- lowerCase <$> readPrompt "Gimme arg: "
          putStrLn name

lowerCase = map toLower

flushString :: String -> IO ()
flushString s = putStr s >> hFlush stdout

readPrompt :: String -> IO String
readPrompt prompt = flushString prompt >> getLine

哦,如果有办法通过Control.ApplicativeControl.Arrow 来实现,我想知道。我对这两个模块非常感兴趣。

谢谢!

【问题讨论】:

    标签: haskell coding-style io conditional command-line-arguments


    【解决方案1】:
    main :: IO ()
    main = do args <- getArgs
              name <- lowerCase <$> case args of
                [arg] -> return arg
                _     -> readPrompt "Gimme arg: "
              putStrLn name
    

    【讨论】:

    • 我喜欢它。它很干净。案例表达式中的模式并非详尽无遗,但很容易修复。
    • @Ionuț G. Stan:我只是一一翻译你的意思。使模式详尽无遗会使我的示例不那么干净。
    • 我将lowerCase &lt;$&gt; 放在case args of 前面,这样命令行arg 也会小写。此外,您可以匹配 [arg]_(而不是 [])以更接近请求的行为。
    • @Dan:合并了这些建议。
    【解决方案2】:

    这不适合您的特定用例,但问题标题让我立即想到了Control.Monad 中的when。直接来自the docs

    when :: Monad m =&gt; Bool -&gt; m () -&gt; m ()

    单子表达式的条件执行。

    例子:

    main = do args <- getArgs
              -- arg <- something like what FUZxxl did..
              when (length args == 1) (putStrLn $ "Using command line arg: " ++ arg)
              -- continue using arg...
    

    您也可以以类似的方式使用when 的表弟unless

    【讨论】:

    • 我也想过when。问题是我需要某种 it/then/else 而不仅仅是 if/then。此外,什么时候不返回任何东西。我将不得不在其中“分配给一个变量”,这可能意味着使用 State monad。不过不太确定。感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多