Haskell中如何将字符串转换为LineItem类型的列表?
解决方案
要实现累积普通字符为单个Word的逻辑,你需要借助辅助递归函数来携带当前累积的字符。核心思路是:用辅助函数跟踪正在构建的单词字符,直到遇到空格/换行时,将累积的字符打包成Word,再继续处理剩余字符串。
修正后的完整代码
-- 1.1 data LineItem = Space | Newline | Word String deriving (Eq) -- 1.2 mkSpace :: LineItem mkSpace = Space mkNewline :: LineItem mkNewline = Newline mkWord :: String -> LineItem mkWord = Word -- 1.3 修正原有的lineItemToStr(原实现会输出带引号的字符串,不符合预期) lineItemToStr :: LineItem -> String lineItemToStr Space = " " lineItemToStr Newline = "\n" lineItemToStr (Word s) = s instance Show LineItem where show = lineItemToStr -- 主函数:调用辅助函数,初始累积字符为空 toLineItems :: String -> [LineItem] toLineItems = toLineItemsHelper "" -- 辅助函数:参数1=当前累积的单词字符,参数2=剩余未处理的字符串 toLineItemsHelper :: String -> String -> [LineItem] -- 情况1:遇到空格 toLineItemsHelper acc (' ':rest) = case acc of "" -> Space : toLineItemsHelper "" rest -- 无累积字符,直接加Space _ -> Word acc : Space : toLineItemsHelper "" rest -- 先把累积的转成Word,再加Space -- 情况2:遇到换行 toLineItemsHelper acc ('\n':rest) = case acc of "" -> Newline : toLineItemsHelper "" rest _ -> Word acc : Newline : toLineItemsHelper "" rest -- 情况3:遇到普通字符,加入累积列表 toLineItemsHelper acc (c:rest) = toLineItemsHelper (acc ++ [c]) rest -- 情况4:字符串处理完毕,若有累积字符则转成Word toLineItemsHelper acc "" = if null acc then [] else [Word acc]
逻辑解释
- 辅助函数的作用:
toLineItemsHelper的第一个参数acc用来临时存储正在构建的单词字符,避免每次递归只处理单个字符。 - 空格/换行的处理:遇到分隔符时,先检查是否有累积的字符——如果有,先将其转为
Word,再添加分隔符对应的LineItem;如果没有,直接添加分隔符。 - 普通字符的处理:将当前字符追加到累积字符串
acc中,继续递归处理剩余部分。 - 收尾处理:当字符串处理完时,若
acc不为空,说明最后还有一个未完成的单词,需要将其转为Word加入结果列表。
测试示例
比如输入字符串"hello world\nfoo",调用toLineItems会得到:
[Word "hello", Space, Word "world", Newline, Word "foo"]
内容的提问来源于stack exchange,提问作者LLScheme
相关产品推荐
相关产品推荐

