Haskell 如何实现mapAccumM?

Haskell 如何实现mapAccumM?,haskell,Haskell,我想要mapM在传递累加器时可以遍历的东西上。我想到了: import Control.Applicative import Data.Traversable import Control.Monad.State mapAccumM :: (Applicative m, Traversable t, MonadState s m) => (s -> a -> m (s, b)) -> s -> t a -> m (t b) mapA

我想要
mapM
在传递累加器时可以遍历的东西上。我想到了:

import Control.Applicative
import Data.Traversable
import Control.Monad.State

mapAccumM :: (Applicative m, Traversable t, MonadState s m)
             => (s -> a -> m (s, b)) -> s -> t a -> m (t b)
mapAccumM f acc0 xs = put acc0 >> traverse g xs
  where
    g x = do
      oldAcc <- get
      (newAcc, y) <- f oldAcc x
      put newAcc
      return y
导入控件。应用程序
导入数据。可遍历
进口控制单体状态
mapAccumM::(应用程序m,可遍历t,单态s m)
=>(s->a->m(s,b))->s->t a->m(t b)
mapAccumM f acc0 xs=put acc0>>遍历g xs
哪里
gx=do

oldAccroconnor在哈斯克尔为我回答了这个问题

这解决了我的问题,但请注意,累加器在元组的第二个元素而不是第一个元素中返回

mapAccumM :: (Monad m, Functor m, Traversable t) => (a -> b -> m (c, a)) -> a -> t b -> m (t c)
mapAccumM f = flip (evalStateT . (Data.Traversable.traverse (StateT . (flip f))))
或返回蓄能器:

mapAccumM' :: (Monad m, Functor m, Traversable t) => (a -> b -> m (c, a)) -> a -> t b -> m (t c, a)
mapAccumM' f = flip (runStateT . (Data.Traversable.traverse (StateT . (flip f))))

你可以在你的函数中使用
StateT
runStateT
,而不要求外部monad是一个状态monad…说清楚了,你想要与
monad m
限制相同的类型,而不是
MonadState s m
?ChrisTaylor:是的,我想要monad,不确定状态monad转换器是否算作“无状态单子”;D