我不知道这方面的技术术语,但正如标题中所述,我正在寻找一个函数或类型类的功能,它将输出一对容器的函数转换为包含一对容器的容器。它的签名应该如下所示
def f[M[_], A, B, C](g: A => (M[B], M[C])): A => M[(B, C)]要实现这一点,可能需要首先指定一个允许映射(M[A], M[B]) => M[(A, B)]的类型类,然后组合一个具有此类型类功能的g。
作为一个具体的例子,假设我们有一个函数f: Int => Option[Int]和一个函数g: Int => Option[Long]。我们可以使用scalaz (val h = f &&& g)中的箭头语法“配对”函数,这样得到的函数(h)就具有Int => (Option[Int], Option[Long])类型。然后,我们可以通过使用for- composing或使用(a, b) => a tuple b合成来对Option进行排序。这是如何概括的?
编辑:
在发表这篇文章后不久,我发现scalaz7中的tuple功能来自Apply类型类,而不是直接来自Option。显然,这是一个比Applicative更弱的类,这解释了为什么它使用一元式的for- class。因此,在一般情况下,应用应该可以完成这项工作。我现在的问题是:如何将原始A => (M[B], M[C])直接转换为A => M[(B, C)],而不是将Apply的功能与原始函数的功能组合在一起?
发布于 2014-02-22 07:44:02
尝尝这个?我还没有安装scalaz。
def f[M <: Monad[M[_]], A, B, C](g: A => (M[B], M[C])): A => M[(B, C)] = (a: A) => {
g(a) match {
// For general monads, converts (M[B],M[C]) to M[(B, C)]
case (b, c) => b.map((_, c)).flatMap(k => k._2.map((k._1, _)))
}
}发布于 2014-02-22 08:04:19
Apply有我需要的东西,下面的方法看起来很有效。我希望更简洁的语法糖,但它已经完成了工作:
def pairApply[M[_] : Apply, A, B, C](g: A => (M[B], M[C])): A => M[(B, C)] = {
g andThen (x => implicitly[Apply[M]].tuple2(x._1, x._2))
}在bazzargh's comment之后,使用scalaz的Zip可以使这一点变得更清楚:
def zipPair[M[_] : Zip, A, B, C](g: A => (M[B], M[C])): A => M[(B, C)] = {
g andThen (x => x._1 fzip x._2)
}然而,构图仍然不理想。
发布于 2014-08-18 03:00:58
还有bisequence,它可以让你把应用程序的元组翻过来:
def zipPair[M[_]: Applicative, A, B, C](g: A => (M[B], M[C])): A => M[(B, C)] =
g.andThen(_.bisequence[M, B, C])它也比Zip更通用,因为它可以在任何类型的Bitraverse实例上工作(例如Either),而不仅仅是元组。
https://stackoverflow.com/questions/21947404
复制相似问题