如何在Relude中实现将[a]转换为[(a,a)]的pairs函数?
适配Relude的
pairs函数实现方案 针对你需要实现pairs :: [a] -> [(a, a)]的需求,由于Relude默认不导出普通列表的tail(仅支持NonEmpty a类型),这里提供几种可行的适配方案:
方案1:显式导入普通列表的tail
Relude出于安全性考量,默认不导出会在空列表抛出异常的普通列表tail,但你可以从Relude.List模块显式导入它,保持原实现逻辑:
import Relude.List (tail) pairs :: [a] -> [(a, a)] pairs x = zip x (tail x)
⚠️ 注意:这个版本和标准Prelude的实现一样,传入空列表时会抛出异常,如果你需要安全处理空列表,建议选择其他方案。
方案2:手动实现无依赖版本(避开tail)
直接通过模式匹配实现,完全不依赖tail,同时天然处理空列表和单元素列表的情况:
pairs :: [a] -> [(a, a)] pairs [] = [] pairs [_] = [] pairs (x:y:xs) = (x, y) : pairs (y:xs)
这个版本效率高,且没有异常风险,是最稳妥的纯手动实现方式。
方案3:利用NonEmpty做安全兼容
如果想利用Relude的NonEmpty类型保证安全性,同时兼容原有的[a]输入类型,可以通过viaNonEmpty转换后处理:
import Relude (NonEmpty(..), viaNonEmpty) pairs :: [a] -> [(a, a)] pairs = maybe [] (\(x :| xs) -> zip (x:xs) xs) . viaNonEmpty id
这里viaNonEmpty id将普通列表转为Maybe NonEmpty a,非空时拆分为首元素和剩余列表,再通过zip生成配对;空列表直接返回空,完全避免异常。
如果可以接受调整函数类型为NonEmpty a -> [(a, a)],实现会更简洁:
import Relude (NonEmpty(..), tail, toList) pairsNE :: NonEmpty a -> [(a, a)] pairsNE xs = zip (toList xs) (tail xs)
再包装一个兼容普通列表的函数:
pairs :: [a] -> [(a, a)] pairs = maybe [] pairsNE . viaNonEmpty id
内容的提问来源于stack exchange,提问作者Steven Pinkerton
相关产品推荐
相关产品推荐

