lef*_*out 5 containers haskell traversable
Traversable在某种意义上,容器类的结构具有"路径"(可以对应于列表),可以在不解散结构的情况下修改其中的元素.于是
zipTrav :: Traversable t => t a -> [b] -> Maybe (t (a,b))
zipTrav = evalStateT . traverse zp
where zp a = do
bs <- get
case bs of
[] -> lift Nothing
(b:bs') -> put bs' >> return (a,b)
Run Code Online (Sandbox Code Playgroud)
但是,列表状态遍历似乎有些过时,可能不是最有效的方法.我认为会有一个完成上述或更一般任务的标准函数,但我无法弄清楚它会是什么.
tzipWith :: Traversable t => (a -> b -> c) -> [a] -> t b -> Maybe (t c)
tzipWith f xs = sequenceA . snd . mapAccumL pair xs
where pair [] y = ([], Nothing)
pair (x:xs) y = (xs, Just (f x y))
tzip :: Traversable t => [a] -> t b -> Maybe (t (a, b))
tzip = tzipWith (,)
ghci> tzip [1..] [4,5,6]
Just [(1,4),(2,5),(3,6)]
ghci> tzip [1,2] [4,5,6]
Nothing
Run Code Online (Sandbox Code Playgroud)
关于效率问题 - 在引擎盖下,mapAccum函数使用状态monad,所以我所做的就是在高阶函数中捕获代码的命令部分.我不希望这段代码比你的代码表现更好.但我认为你不能比Statemonad(或ST)做得更好Traversable t.