Monadic改为元组

时间:2015-08-13 02:37:48

标签: haskell lens

我正在寻找类似于以下类型的函数:

Monad m => (a, b) -> (b -> m c) -> m (a, c)

在我看来,它是绑定(>>=)和镜头操作的一些组合。

我知道我可以在绑定后使用模式匹配来解决这个问题,但我的直觉告诉我,通过利用镜头来编写这个“更简单”的方法。

有没有这样的操作?

2 个答案:

答案 0 :(得分:8)

这绝对是镜头。 monad实际上只是一点点分心,因为你需要的只是一个仿函数:

changesecond (a, b) f = fmap (a,) (f b)

我非常确定_2镜头可以用over之类的基本镜头进行竞价,但我还不熟悉这个库。

修改

确实不需要组合器。你可以写

changesecond pair f = _2 f pair

您应该能够从Lens类型的一般定义中解决这个问题。

编辑2

这个简单的例子展示了Van Laarhoven镜片结构的主题:

  1. 从上下文中提取焦点。
  2. 应用给定的函数以产生一系列有趣的结果。
  3. 使用fmap将上下文恢复为结果。
  4. Ed Kmett的lens图书馆以各种方式详细阐述了这一主题。有时它会加强仿函数约束。有时它会将函数概括为profunctor。在Equality的情况下,它会删除仿函数约束。事实证明,相同的基本类型形状可以表达许多不同的想法。

答案 1 :(得分:6)

如果您将forM = flip mapM约束放宽到for = flip traverse,则您的功能只是MonadApplicative。正在遍历的Functor(,) a

Prelude> let foo :: Applicative f => (a, b) -> (b -> f c) -> f (a, c); foo p k = traverse k p
Prelude> :t foo
foo :: Applicative f => (a, b) -> (b -> f c) -> f (a, c)
Prelude> foo (1,2) (\x -> [x,2*x])
[(1,2),(1,4)]

(另外,正如dfeuer指出的那样,在这种特殊情况下你甚至不需要Applicative。)