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 == foo和p == _ < _.对于scalaz来说,必然会有一些熟练的聪明才智!我可以看到使用BooleanW我可以写:
p(f(a), f(b)).option(a).getOrElse(b)
Run Code Online (Sandbox Code Playgroud)
但我确信我能够编写一些只引用a和b一次的代码.如果这存在,它必须是某种组合Function1W和其他东西,但scalaz对我来说有点神秘!
编辑:我想我在这里问的不是"我怎么写这个?" 但是"这个功能的正确名称和签名是什么?它与FP的东西有什么关系,我还不知道像Kleisli,Comonad等?"
万一它不在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)
我不认为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)
所述***组合子有两个输入端和运行在第一,第二各自的参数的第一和第二指定的函数.>>>然后将此箭头与进行比较的箭头组合在一起.
但正如我所说 - 写这篇文章可能没有任何理由.