You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中split函数单行实现诉求:期望纳入Prelude并由base函数组合

用Base库实现可纳入Prelude的Split函数

嘿,这个问题我太有共鸣了——split绝对是文本处理里的刚需,但base库偏偏没把它直接放进Prelude,每次要自己实现确实有点挠头。不过用base里的现有函数完全能写出简洁好用的版本,我给你分享几个实用的思路:

1. 单个字符分隔的基础递归版本

这是最直观也最简洁的实现,只用了Prelude自带的break函数和模式匹配,处理连续分隔符时也能保留空字符串(比如split ',' "a,,b"会得到["a","","b"]):

split :: Eq a => a -> [a] -> [[a]]
split delim s = case break (== delim) s of
    (chunk, _:rest) -> chunk : split delim rest  -- 找到分隔符,取出前半段继续递归
    (chunk, [])     -> [chunk]                   -- 没有分隔符了,返回最后一段

2. 用unfoldr实现更紧凑的版本

如果你喜欢更函数式的风格,可以用Data.List里的unfoldr(Data.List默认被Prelude包含,不需要额外导入),代码更紧凑:

import Data.List (unfoldr)

split :: Eq a => a -> [a] -> [[a]]
split delim = unfoldr $ \remaining ->
    if null remaining
        then Nothing
        else let (chunk, rest) = break (== delim) remaining
             in Just (chunk, drop 1 rest)

3. 支持字符串分隔符的版本

如果需要按字符串而非单个字符分割(比如按"||"分割文本),可以用base的isPrefixOf实现:

import Data.List (isPrefixOf)

splitOn :: Eq a => [a] -> [a] -> [[a]]
splitOn delim s
    | null delim = error "splitOn: 分隔符不能为空字符串"
    | null s     = []
    | delim `isPrefixOf` s = splitOn delim (drop (length delim) s)
    | otherwise   = let (c:cs) = s
                    in case splitOn delim cs of
                        [] -> [[c]]
                        (first:rest) -> (c:first) : rest

这个版本会正确处理比如splitOn "||" "a||b|||c"得到["a","b","","c"]的场景。

加入自定义Prelude

把这些函数放到你自己的自定义Prelude模块里(比如MyPrelude.hs),然后在项目里默认导入它,就能像用原生Prelude函数一样用split了!

内容的提问来源于stack exchange,提问作者luochen1990

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:02:41