看起来@Benjamin Hodgson 误读了您的问题,并认为您想f
将其应用于每个部分结果中的单个元素。因此,您最终认为他的方法不适用于您的问题,但我认为它确实适用。考虑以下变化:
import Control.Monad.State
indexed :: (Traversable t) => t a -> (t (Int, a), Int)
indexed t = runState (traverse addIndex t) 0
where addIndex x = state (\k -> ((k, x), k+1))
scanMap :: (Traversable t) => (a -> a) -> t a -> [t a]
scanMap f t =
let (ti, n) = indexed (fmap (\x -> (x, f x)) t)
partial i = fmap (\(k, (x, y)) -> if k < i then y else x) ti
in map partial [1..n]
在这里,indexed
在状态 monad 中操作以向可遍历对象的元素添加递增索引(并“免费”获取长度,无论这意味着什么):
> indexed ['a','b','c']
([(0,'a'),(1,'b'),(2,'c')],3)
而且,正如 Ben 指出的那样,它也可以使用以下方式编写mapAccumL
:
indexed = swap . mapAccumL (\k x -> (k+1, (k, x))) 0
然后,scanMap
获取可遍历对象,将其 fmap 到类似的前/后对结构,用于indexed
索引它,并应用一系列partial
函数,其中partial i
为第一个i
元素选择“afters”,为其余元素选择“befores”。
> scanMap (*2) [1,2,3]
[[2,2,3],[2,4,3],[2,4,6]]
至于将其从列表概括为其他内容,我无法弄清楚您要对第二个签名做什么:
func :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a)
因为如果你把它专门用于一个列表,你会得到:
func' :: (Traversable t) => (a -> [a]) -> t a -> [t a]
而且完全不清楚您希望在这里做什么。