【问题标题】:How can I combine a tuple of values with a tuple of functions?如何将值元组与函数元组结合起来?
【发布时间】:2015-02-18 22:13:42
【问题描述】:

我有可用的 scalaZ。

我有一个(A, B) 和一个(A => C, B => D),我想以一种简单易读的方式获得一个(C, D)

我觉得我可以用应用程序做一些事情,但我找不到合适的方法。

【问题讨论】:

标签: scala functional-programming scalaz applicative


【解决方案1】:

编辑

一开始没明白,OP 有函数元组。在这种情况下,如 cmets 建议的那样,这应该可以工作:

val in = ("1", 2)

val fnT = ((s: String) => s.toInt, (i: Int) => i.toString)

val out = (in.bimap[Int, String] _).tupled(fnT)

如果你有两个函数并且想在元组上应用它们,你应该可以这样做:

import scalaz._
import Scalaz._

val in = ("1", 2)

val sToi = (s: String) => s.toInt
val iTos = (i: Int) => i.toString


val out = sToi <-: in :-> iTos
// or
val out1 = in.bimap(sToi, iTos)
// or
val out2 = (sToi *** iTos)(in)

【讨论】:

  • 这可行,但需要撕掉元组。我认为 OP 想要类似funTuple appliedTo tuple2
  • 您可以将tupled 应用到bimap,然后传入函数元组
  • @BenReich 当我尝试调用ab.bimap.tupled 时出现编译错误 - 可能是因为 bimap 是通过隐式提供的?我不知道。控制台给了我一个不同的错误,scala&gt; ab.bimap.tupled(fs) => error: missing arguments for method bimap in class BifunctorOps; follow this method with _' 如果你想把它当作一个部分应用的函数, but I can't find any combination of _`让它工作
  • 有趣。我不使用scalaz,所以在发表评论之前我没有测试它,它似乎可以工作!也许是隐含的,就像你说的那样。
  • 如果你提供类型,你可以这样做:in.bimap[Int, String] _ tupled tupledFuncs
【解决方案2】:

箭头?比如:

(f *** g)(a, b)

http://eed3si9n.com/learning-scalaz/Arrow.html

【讨论】:

    【解决方案3】:

    我没有发现 scalaz 更具可读性。定义自己的函数有什么问题。

    def biFunc(valTup:(A,B), funTup:((A)=>C,(B)=>D)):(C,D) = (funTup._1(valTup._1), funTup._2(valTup._2))
    

    【讨论】:

      【解决方案4】:

      我同意 Lionel Port 的观点,但您可以通过以下方式使其更具可读性:

      case class BiFun[A,B,C,D](f1:A=>C, f2: B=>D){
        def applyTo(a: (A,B)) = (f1(a._1), f2(a._2))
      } 
      
      object BiFun{  
        implicit def toBiFun(a: (A=>C, B=>D)) = BiFun(a._1, a._2) 
      }
      

      类似:

      import BiFun._
      val ab = (A(1), B(2))
      val ac = (x: A) => C(x.i+2)
      val bd = (x: B) => D(x.i+2)
      val bifn = (ac, bd)
      bifn applyTo ab
      

      所以,最终你会得到funTuple applyTo tuple 并获得最高级别的可读性

      【讨论】:

        【解决方案5】:

        自己编写这个方法可能是最好的选择:

        def bimap[A,B,C,D](vals:(A, B), funcs:(A=>C, B=>D)):(C,D) = {
            val ((func1, func2), (val1, val2)) = funcs -> vals
            func1(val1) -> func2(val2)
        }
        

        如果你经常这样做,你甚至可以增强元组类:

        implicit class EnhancedTuple2[A, B](val vals: (A, B)) extends AnyVal {
            def bimap[C, D](funcs: (A=>C, B=>D)) = {
                val ((func1, func2), (val1, val2)) = funcs -> vals
                func1(val1) -> func2(val2)
            }
        }
        

        这样你就可以做到:

        val func1: Int => Int = x => x * x
        val func2: Int => String = x => x.toString
        val tupledFuncs = func1 -> func2
        (1, 2).bimap(tupledFuncs)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-22
          • 1970-01-01
          • 2014-12-29
          • 2020-11-16
          • 2017-01-22
          • 2015-06-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多