对元组的单子改变
Monadic alteration to tuple
我正在寻找类似于以下类型的函数:
Monad m => (a, b) -> (b -> m c) -> m (a, c)
在我看来,它是绑定 (>>=
) 和镜头操作的某种组合。
我知道我可以在绑定后使用模式匹配来解决这个问题,但我的直觉告诉我有一种 "simpler" 方法可以通过利用镜头来编写它。
有没有这样的操作?
如果您将 Monad
限制放宽到 Applicative
,您的函数就是 forM = flip mapM
,或者 for = flip traverse
。遍历的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
。)
这绝对是 lensy。 monad 实际上只是有点让人分心,因为你只需要一个函子:
changesecond (a, b) f = fmap (a,) (f b)
我很确定 _2
镜头可以用像 over
这样的基本镜头来满足你的要求,但我对图书馆还不太熟悉。
编辑
真的不需要组合器。你可以写
changesecond pair f = _2 f pair
您应该能够从 Lens
类型的一般定义中解决这个问题。
编辑 2
这个简单的例子展示了 Van Laarhoven 镜头构造的主题:
- 从上下文中提取焦点。
- 应用给定的函数产生一个函数式的结果。
- 使用
fmap
将上下文恢复为结果。
Ed Kmett 的 lens
图书馆以各种方式阐述了这个主题。有时它会加强函子约束。有时它会将功能概括为发音器。在 Equality
的情况下,它删除了函子约束。原来同一个基本型的形状可以表达出很多不同的想法。
我正在寻找类似于以下类型的函数:
Monad m => (a, b) -> (b -> m c) -> m (a, c)
在我看来,它是绑定 (>>=
) 和镜头操作的某种组合。
我知道我可以在绑定后使用模式匹配来解决这个问题,但我的直觉告诉我有一种 "simpler" 方法可以通过利用镜头来编写它。
有没有这样的操作?
如果您将 Monad
限制放宽到 Applicative
,您的函数就是 forM = flip mapM
,或者 for = flip traverse
。遍历的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
。)
这绝对是 lensy。 monad 实际上只是有点让人分心,因为你只需要一个函子:
changesecond (a, b) f = fmap (a,) (f b)
我很确定 _2
镜头可以用像 over
这样的基本镜头来满足你的要求,但我对图书馆还不太熟悉。
编辑
真的不需要组合器。你可以写
changesecond pair f = _2 f pair
您应该能够从 Lens
类型的一般定义中解决这个问题。
编辑 2
这个简单的例子展示了 Van Laarhoven 镜头构造的主题:
- 从上下文中提取焦点。
- 应用给定的函数产生一个函数式的结果。
- 使用
fmap
将上下文恢复为结果。
Ed Kmett 的 lens
图书馆以各种方式阐述了这个主题。有时它会加强函子约束。有时它会将功能概括为发音器。在 Equality
的情况下,它删除了函子约束。原来同一个基本型的形状可以表达出很多不同的想法。