如何使用"base"中的函数实现"intercalate"的反转(将字符串拆分成字符)?

 zhan168 发布于 2023-02-08 13:51

我想在换行符上拆分一个字符串,我很惊讶我找不到反函数intercalate "\n".也就是说,一个函数将字符串拆分成新行(或根据其他谓词).

请注意lineswords做一些不同的事情.例如

intercalate "\n" (lines "a\n") == "a"

还有一个类似的功能函数splitOn拆分库.我也可以直接自己编写这样的函数:

splitOn :: (a -> Bool) -> [a] -> [[a]]
splitOn p = map reverse . g []
  where
    g rs []                 = [rs]
    g rs (x:xs) | p x       = rs : g [] xs
                | otherwise = g (x : rs) xs

但我想知道是否只使用base中的函数可以更容易地构建它.

2 个回答
  • 如果更原始函数的组合是你在找什么,那么我能想到的基础上比什么没有别的办法unfoldrbreak,但unfoldr不是Prelude.

    无论如何,我认为你很清楚,这Prelude远远不是我们许多人想要的那样,所以毫无疑问它甚至无法解决这样一个看似微不足道的问题.一般的问题Prelude似乎是它的错误:该模块的目的是提供足以与Haskell一起玩的东西作为介绍的一部分,正如它的名字所示,但由于没有标准的"基础"模块,Haskellers倾向于把它视为一体.

    2023-02-08 13:53 回答
  • 正如尼基塔·沃尔科夫所指出的那样,限制"只有Prelude功能"并不容易,但这里有一个选择:

    splitWhen p [] = [[]]
    splitWhen p l  = uncurry (:) . fmap (splitWhen p . drop 1) . break p $ l
    

    这使用Functor实例(,) a作为替代Control.Arrow.second(以避免凌乱的lambda表达式),它可以在不导入任何东西的情况下工作(ghci说"在'GHC.Base'中定义'"),但我不确定它是否真的属于Prelude,因为我在Haskell报告中找不到它.

    编辑:被允许使用其他功能base甚至没有帮助我那么多.在任何情况下,我会使用second而不是fmap因为我认为它增加了一点清晰度.使用unfoldr,使用Maybe种子来区分字符串的结尾和空白部分(或示例中的空行):

    import Control.Applicative ((<$>))
    import Control.Arrow (second)
    import Data.List (unfoldr)
    
    splitWhen p = unfoldr (second check . break p <$>) . Just
      where
        check []       = Nothing
        check (_:rest) = Just rest
    
    -- or cramming it into a single line with 'Data.Maybe.listToMaybe'
    splitWhen' p =
      unfoldr (second (\rest -> tail rest <$ listToMaybe rest) . break p <$>) . Just
    

    2023-02-08 13:53 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有