gpt4 book ai didi

haskell - 读取多行用户输入

转载 作者:行者123 更新时间:2023-12-02 16:54:54 24 4
gpt4 key购买 nike

我想懒洋洋地读取用户输入并逐行执行某些操作。但是,如果用户以 , (逗号)后跟任意数量的空格(包括零)结束一行,我想给他机会在下一行完成输入。

这是我得到的:

import System.IO
import Data.Char

chop :: String -> [String]
chop = f . map (++ "\n") . lines
where f [] = []
f [x] = [x]
f (x : y : xs) = if (p . tr) x
then f ((x ++ y) : xs)
else x : f (y : xs)
p x = (not . null) x && ((== ',') . last) x
tr xs | all isSpace xs = ""
tr (x : xs) = x :tr xs

main :: IO ()
main =
do putStrLn "Welcome to hell, version 0.1.3!"
putPrompt
mapM_ process . takeWhile (/= "quit\n") . chop =<< getContents
where process str = putStr str >> putPrompt
putPrompt = putStr ">>> " >> hFlush stdout

抱歉,它根本不起作用。该死的困惑。

P.S.我想在每个 block 的末尾保留 \n 字符。目前,我在 lines 之后使用 map (++ "\n") 手动添加它们。

最佳答案

稍微改变一下chop的类型怎么样:

readMultiLine :: IO [String]
readMultiLine = do
ln <- getLine
if (endswith (rstrip ln) ",") then
liftM (ln:) readMultiLine
else
return [ln]

现在您知道,如果最后一个列表不为空,则用户尚未完成输入(最后一个输入以 ',' 结尾)。

当然,可以导入 Data.String.Utils,或者编写您自己的。可能很简单:

endswith xs ys = (length xs >= length ys)
&& (and $ zipWith (==) (reverse xs) (reverse ys))
rstrip = reverse . dropWhile isSpace . reverse

但我一开始就没有捕获重点。这就是实际情况。

unfoldM :: (Monad m) => (a -> Maybe (m b, m a)) -> a -> m [b]
unfoldM f z = case f z of
Nothing -> return []
Just (x, y) -> liftM2 (:) x $ y >>= unfoldM f

main = unfoldM (\x -> if (x == ["quit"]) then Nothing
else Just (print x, readMultiLine)) =<< readMultiLine

原因是,您需要能够在读取一个多行输入和下一个多行输入之间插入要在输入上完成的“操作”。这里 print x 是插入到两个 readMultiLine

之间的操作<小时/>

既然您对 getContents 有疑问,请让我补充一下。尽管 getContents 提供了惰性 String,但它对世界的有效更改是按照处理列表的后续效果排序的。但是列表的处理尝试在读取特定列表项的效果之间插入效果。为此,您需要一个公开效果链的函数,以便您可以在它们之间插入您自己的效果。

关于haskell - 读取多行用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26483920/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com