推广所有仿函数的"序列"?

Bru*_*rry 6 monads haskell functor

我有这个代码:

fmapM :: Monad m => (a -> m b) -> (t, a) -> m (t, b)
fmapM f (id, e) = do 
  ev <- f e
  return (id, ev)
Run Code Online (Sandbox Code Playgroud)

它基本上将函数应用于元组中的第二个元素,然后"提取"monad.由于元组是一个函子,有没有办法为所有函子推广这个?我想不出一个实现,但类型签名应该是:

fmapM :: (Monad m, Functor f) => (a -> m b) -> f a -> m f b
Run Code Online (Sandbox Code Playgroud)

看起来第二步似乎是一个"序列"操作,它从另一个仿函数(列表)中提取monad.但序列并非一般化为所有仿函数.你能想出fmapM的通用实现吗?

编辑:我已经意识到旧版本的拥抱确实已经实现了这个功能.但是,我找不到代码.现在,建议我使用foldable/traversable来实现相同的目的.

sha*_*haf 11

您正在寻找的功能traverse来自Data.Traversable:

traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
Run Code Online (Sandbox Code Playgroud)

请注意,你不能traverse任何Functor-例如,(r ->)-所以有一个单独的子Traversable函子.另请注意,您不需要Monad- 只是Applicative(这种概括很有用).