代码之家  ›  专栏  ›  技术社区  ›  oxbow_lakes

在依赖于布尔值的双分支器的“边”上调用函数

  •  8
  • oxbow_lakes  · 技术社区  · 14 年前

    如果我有一个 Bifunctor[A,A] bf,函数 f : A => A 和A Boolean 价值 p :

    def calc[A, F[_,_]: Bifunctor](p: Boolean, bf: F[A, A], f: A => A): F[A, A] = {
      val BF = implicitly[Bifunctor[F]]
      BF.bimap(bf, (a : A) => if (p) f(a) else a, (a : A) => if (!p) f(a) else a)
    }
    

    我怎样才能更简洁(更富有表现力)地表达这一点呢?基本上,我尝试在 双离合器 (例如 Tuple2 )依赖于某个谓词。如果谓词为真,如果为假,我想映射lhs和rhs

    val t2 = (1, 2)
    def add4 = (_ : Int) + 4
    calc(true, t2, add4) //should be (5,2)
    calc(false, t2, add4) //should be (1,6)
    


    假设我想使用元组(而不是更一般的 Bifunctor )我似乎可以使用 arrows 如下所示 :
    def calc[A](p: Boolean, bf: (A, A), f: A => A): (A, A) 
      = (if (p) f.first[A] else f.second[A]) apply bf
    
    3 回复  |  直到 14 年前
        1
  •  4
  •   Apocalisp    14 年前

    不是所有更好的:

    def calc[A, F[_,_]:Bifunctor](p: Boolean, bf: F[A, A], f: A => A): F[A, A] =
       (if (p) (bf :-> (_: A => A)) else ((_:A => A) <-: bf))(f)
    

    稍微好一点:

    def cond[A:Zero](b: Boolean, a: A) = if (b) a else mzero
    
    def calc[A, F[_,_]:Bifunctor](p: Boolean, bf: F[A, A], f: Endo[A]): F[A, A] =
      cond(p, f) <-: bf :-> cond(!p, f)
    

    一些哈斯凯尔人,只是为了语言嫉妒:

    calc p = if p then first else second
    
        2
  •  0
  •   Community CDub    7 年前

    这个变化是在 Apocalisp's solution 工作?

    def calc[A, F[_,_]:Bifunctor](p: Boolean, bf: F[A, A], f: A => A): F[A, A] =
       (if (p) ((_: F[A,A]) :-> f) else (f <-: (_: F[A,A])))(bf)
    

    注意:我没有用scalaz测试这个。

        3
  •  0
  •   Rex Kerr    14 年前

    编辑:固定返回 (A,A) 而不是 A

    也许我遗漏了一些东西,但这不是临时变量的作用吗?使用常规scala元组:

    Some(bf).map(x => if (p) x.copy(_1 = f(x._1)) else x.copy(_2 = f(x._2))).get
    

    { val (l,r) = bf; if (p) (f(l),r) else (l,f(r)) }