Вызов функции на «стороне» Bifunctor в зависимости от значения логического - PullRequest
8 голосов
/ 11 ноября 2010

Если у меня есть экземпляр Bifunctor[A,A] bf, функция f : 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), зависящего от некоторого предиката. Если предикат равен true, я хочу отобразить LHS и RHS, если он равен false

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), я, кажется, могу использовать стрелки следующим образом :

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 ]

4 голосов
/ 11 ноября 2010

Не так много приятнее:

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)

Немного Haskell, просто для зависти в языке:

calc p = if p then first else second
0 голосов
/ 11 ноября 2010

Работает ли этот вариант для решения Apocalisp ?

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)

Примечание: я не проверял это со скалязом.

0 голосов
/ 11 ноября 2010

Редактировать: исправлено возвращать (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)) }
...