我正在尝试从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
提前谢谢!
答案 0 :(得分:2)
看来你想:
这是一种使用惰性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"
以下是它的工作原理:
contents <- getContents
将所有标准输入读入变量contents
lines contents
将输入分解为行forM_ ...
遍历每一行,将该行传递给process
函数诀窍是getContents
懒惰地读取标准输入,以便在读取每一行后得到一些输出。
您应该知道,当您的程序变得更复杂时,您可能会遇到懒惰IO的问题。但是,对于这个简单的用例,懒惰的IO非常好并且运行良好。