函数等价于if(p(f(a),f(b))a else b

oxb*_*kes 14 functional-programming scala scalaz

我猜测必须有更好的功能方式来表达以下内容:

def foo(i: Any) : Int

if (foo(a) < foo(b)) a else b 
Run Code Online (Sandbox Code Playgroud)

所以在这个例子f == foop == _ < _.对于scalaz来说,必然会有一些熟练的聪明才智!我可以看到使用BooleanW我可以写:

p(f(a), f(b)).option(a).getOrElse(b)
Run Code Online (Sandbox Code Playgroud)

但我确信我能够编写一些只引用ab一次的代码.如果这存在,它必须是某种组合Function1W和其他东西,但scalaz对我来说有点神秘!

编辑:我想我在这里问的不是"我怎么写这个?" 但是"这个功能的正确名称和签名是什么?它与FP的东西有什么关系,我还不知道像Kleisli,Comonad等?"

Tho*_*ung 6

万一它不在Scalaz中:

def x[T,R](f : T => R)(p : (R,R) => Boolean)(x : T*) =
  x reduceLeft ((l, r) => if(p(f(l),f(r))) r else l)

scala> x(Math.pow(_ : Int,2))(_ < _)(-2, 0, 1)
res0: Int = -2
Run Code Online (Sandbox Code Playgroud)

替代一些开销但更好的语法.

class MappedExpression[T,R](i : (T,T), m : (R,R)) {
  def select(p : (R,R) => Boolean ) = if(p(m._1, m._2)) i._1 else i._2 
}

class Expression[T](i : (T,T)){
  def map[R](f: T => R) = new MappedExpression(i, (f(i._1), f(i._2)))
}

implicit def tupleTo[T](i : (T,T)) = new Expression(i)

scala> ("a", "bc") map (_.length) select (_ < _)
res0: java.lang.String = a
Run Code Online (Sandbox Code Playgroud)


Tom*_*cek 5

我不认为Arrows或任何其他特殊类型的计算在这里有用.毕竟,你用正常值计算,你通常可以将计算提升到特殊类型的计算中(arr用于箭头或return单子).

但是,一个非常简单的箭头就是arr a b一个函数a -> b.然后,您可以使用箭头将代码拆分为更原始的操作.但是,可能没有理由这样做,它只会使您的代码更复杂.

例如,您可以将呼叫提升至foo与比较分开进行.这是F#中箭头的简单定义 - 它声明***>>>箭头组合器以及arr将纯函数转换为箭头:

type Arr<'a, 'b> = Arr of ('a -> 'b)
let arr f = Arr f
let ( *** ) (Arr fa) (Arr fb) = Arr (fun (a, b) -> (fa a, fb b))
let ( >>> ) (Arr fa) (Arr fb) = Arr (fa >> fb)
Run Code Online (Sandbox Code Playgroud)

现在您可以像这样编写代码:

let calcFoo = arr <| fun a -> (a, foo a)    
let compareVals = arr <| fun ((a, fa), (b, fb)) -> if fa < fb then a else b

(calcFoo *** calcFoo) >>> compareVals
Run Code Online (Sandbox Code Playgroud)

所述***组合子有两个输入端和运行在第一,第二各自的参数的第一和第二指定的函数.>>>然后将此箭头与进行比较的箭头组合在一起.

但正如我所说 - 写这篇文章可能没有任何理由.

  • 我对这个答案几乎一无所知.+1 (7认同)