推广所有仿函数的“序列”?

时间:2013-07-10 04:15:32

标签: haskell monads functor

我有这段代码:

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

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

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

似乎第二步是“序列”操作,它从另一个仿函数(列表)中提取monad。但序列并不适用于所有仿函数。你能想出一个fmapM的通用实现吗?

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

1 个答案:

答案 0 :(得分:11)

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

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

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