使用Haskell中的参数从标准输入读入多行

时间:2016-05-10 16:10:28

标签: haskell

我正在尝试从Haskell中的标准输入中读取多行,加上一个参数,然后对当前行执行某些操作并将某些内容写入标准输出。

在我的情况下,我试图规范化lambda表达式。程序可以接收1个或多个lambda表达式以进行标准化,然后必须将结果(标准化形式或错误)写入标准输出。并且程序可以接收参数(最大减少数)。这是主要功能:

main :: IO ()
main = do
  params <- getArgs
  fullLambda <- getLine
  let lambda = convertInput fullLambda
  let redNum | (length params) == 1 = read (head params)
             | otherwise = 100
  case (parsing lambda) of
    Left  errorExp -> putStrLn ("ERROR: " ++ lambda)
    Right lambdaExp -> do
      let normalizedLambdaExp = reduction lambdaExp redNum
      if (isNormalForm normalizedLambdaExp) && (isClosed lambdaExp)
        then putStrLn ("OK: " ++ show normalizedLambdaExp)
        else putStrLn ("ERROR: " ++ lambda)
  where
    convertInput :: String -> String
    convertInput ('\"':xs) = take ((length xs) - 2) xs
    convertInput input = input

因此,此代码处理一行并完成缩减,然后将某些内容写入标准输出。如何更改此项以处理多行?我读过关于 replicateM 但我似乎无法理解它。我的思绪非常好,所以我想某种方式可能有些循环,但这肯定不是首选方式。

此外,该程序必须能够像这样运行:

echo "(\x.x) (\x.x)" | Main 25

并将产生:

OK: (\x.x)

如果有多行,则必须为新行生成相同类型的输出。

但是也必须在没有参数的情况下工作,并且必须处理多行。我花时间在谷歌和这里,但我不确定如何阅读论证。我需要一次或多次读入参数和一行。有人知道这个问题不是太冗长的解决方案吗?

我也是这样尝试过的(势在必行):

main :: IO ()
main = do
  params <- getArgs
  mainHelper params
  main

mainHelper :: [String] -> IO ()
mainHelper params = do
  fullLambda <- getLine

依此类推,但它也把它放到了标准输出中:

Main: <stdin>: hGetLine: end of file

提前谢谢!

1 个答案:

答案 0 :(得分:2)

看来你想:

  1. 解析可能存在或不存在的命令行选项。
  2. 对于每一行输入过程,它都有一些功能。
  3. 这是一种使用惰性IO的方法:

    import System.Environment
    import Control.Monad
    
    main = do args <- getArgs
              let option = case args of
                             []    -> ... the default value...
                             (a:_) -> read a
    
              contents <- getContents
              forM_ (lines contents) $ \aline -> do
                process option aline
    

    我假设您的处理函数的类型为process :: Int -> String -> IO ()。例如,它可能看起来像:

    process :: Int -> String -> IO ()
    process option str = do
      if length str < option
        then putStrLn $ "OK: " ++ str
        else putStrLn $ "NOT OK: line too long"
    

    以下是它的工作原理:

    1. contents <- getContents将所有标准输入读入变量contents
    2. lines contents将输入分解为行
    3. forM_ ...遍历每一行,将该行传递给process函数
    4. 诀窍是getContents懒惰地读取标准输入,以便在读取每一行后得到一些输出。

      您应该知道,当您的程序变得更复杂时,您可能会遇到懒惰IO的问题。但是,对于这个简单的用例,懒惰的IO非常好并且运行良好。