haskell - 如何获取 Haskell 中字符串列表的跨度索引?
问题描述
我有一个字符串列表,如下所示:
[Left "hey here are some words",Right "blue",Left "and some other words"]
我想获得每个的跨度索引,因为它们都是一个长字符串的一部分。所以它会输出:
[Left (0, 23), Right (24, 28), Left (29, 49)]
我可以使用mapEither f = fmap $ either (Left . f) (Right . f . fst)
. 所以我可以使用lengths = mapEither length xs
.
此外,我发现我可能需要使用的功能是scanl1
,它的工作方式如下:
> scanl1 (+) [23, 4, 20]
[23, 27, 47]
但我正在努力将它们放在一起。这是我到目前为止所拥有的一切:
import Data.Either
testString = [Left "hey here are some words",Right "blue",Left "and some other words"]
getIndices :: [Either T.Text (T.Text, T.Text)] -> [Integer]
getIndices xs = mapEither length xs where
mapEither f = fmap $ either (Left . f) (Right . f)
lengths = mapEither length xs
spans = scanl1 (mapEither (+)) lengths -- This is wrong
我敢肯定,我让自己变得比需要的更难。
解决方案
这可能是xy 问题,因为Either
通常表示“一个值或另一个值”,并且这些值通常具有不同的含义,并且不会像您的问题那样“聚集在一起”。
由于Functor
和的Applicative
实例Either
不允许您同时在双方工作,您可以构建自己的 fmap 函数:
fmapEither :: (a -> b) -> Either a a -> Either b b
fmapEither f (Left a) = Left $ f a
fmapEither f (Right a) = Right $ f a
然后剩下的就容易一些了:
eitherSpans list = zip <*> tail $ scanl (\acc x -> acc + either length length x) 0 list
--[(0,23),(23,27),(27,47)]
getIndices list = zipWith (\a b -> fmapEither (const a) b) (eitherSpans list) list
--[Left (0,23),Right (23,27),Left (27,47)]
--Or pointfree:
getIndices' = zipWith (fmapEither . const) =<< eitherSpans
编辑
fmapEither
您可以使用Data.Bifunctor代替bimap
custom ,但这有点麻烦,因为您必须重复映射函数:
fmapEither f either ≡ bimap f f either
推荐阅读
- laravel - 如何使用 element-ui 制作带有固定侧边菜单的固定标题
- assembly - 您将如何访问汇编中文本输入的第一个字符
- python - 如何从我的终端/提示/shell 运行此代码
- python - 矩阵乘法
- c++ - 如何在 Visual Studio 项目中“单独”运行 C++ 文件而不受其他文件的影响?
- java - 如何在 React 应用程序中使用 Java 和 MySQL 作为数据库。有什么建议吗?
- flutter - Flutter 无法垂直拖动 pageview
- python - 在函数中使用 reindex 只会产生 NaN 值
- python - 介绍屏幕未加载
- c++ - 获取已安装 GPU 模型的任何正确方法