6

我有这个代码:

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

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

fmapM :: (Monad m, Functor f) => (a -> m b) -> f a -> m f b

第二步似乎是一个“序列”操作,它从另一个函子(列表)中提取单子。但是序列并没有推广到所有的函子。你能想出一个通用的 fmapM 实现吗?

编辑:我意识到旧版本的拥抱确实实现了这个功能。但是,我找不到代码。现在,建议我使用可折叠/可遍历来实现相同的目的。

4

1 回答 1

11

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

traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

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

于 2013-07-10T04:33:23.160 回答