Bueno, miré hacia arriba Hoogle para una firma de tipo como el de Thomas Jung'sanswer, y hay on
. Esto es lo que han buscado:
(a -> b) -> (b -> b -> Bool) -> a -> a -> a
Dónde (a -> b)
es el equivalente de foo
, (b -> b -> Bool)
es el equivalente de <
. Por desgracia, la firma de on
vuelve algo más:
(b -> b -> c) -> (a -> b) -> a -> a -> c
Esto es casi lo mismo, si se reemplaza con c
Bool
y a
en los dos lugares que aparece, respectivamente.
Entonces, en este momento, sospecho que no existe. Se me ha ocurrido que hay una firma de tipo más general, por lo que lo probamos así:
(a -> b) -> ([b] -> b) -> [a] -> a
Ésta dio nada.
EDIT:
Ahora no creo que yo estaba lejos de todo. Consideremos, por ejemplo, esto:
Data.List.maximumBy (on compare length) ["abcd", "ab", "abc"]
La función maximumBy
firma es (a -> a -> Ordering) -> [a] -> a
, lo que, combinado con on
, es bastante cercano a lo especificado originalmente, dado que es Ordering
tiene tres valores - casi un booleano!:-)
Por lo tanto, dicen que escribió on
en Scala:
def on[A, B, C](f: ((B, B) => C), g: A => B): (A, A) => C = (a: A, b: A) => f(g(a), g(b))
El podría escribir select
así:
def select[A](p: (A, A) => Boolean)(a: A, b: A) = if (p(a, b)) a else b
Y utilizar de esta manera:
select(on((_: Int) < (_: Int), (_: String).length))("a", "ab")
Lo que realmente funciona mejor con currying y notación sin puntos. :-) Pero vamos a intentarlo con implícitos:
implicit def toFor[A, B](g: A => B) = new {
def For[C](f: (B, B) => C) = (a1: A, a2: A) => f(g(a1), g(a2))
}
implicit def toSelect[A](t: (A, A)) = new {
def select(p: (A, A) => Boolean) = t match {
case (a, b) => if (p(a, b)) a else b
}
}
entonces usted puede escribir
("a", "ab") select (((_: String).length) For (_ < _))
Muy cerca. No he encontrado ninguna forma de eliminar el calificador de tipo de allí, aunque sospecho que es posible. Quiero decir, sin ir por el camino de respuesta de Thomas. Pero tal vez es el camino. De hecho, creo que on (_.length) select (_ < _)
lee mejor que map (_.length) select (_ < _)
.
Tengo la vaga sensación de que esto podría expresarse muy bien con Arrows in Scalaz. Informará de nuevo con algo más concreto después :) – retronym
'List (a, b) minBy foo'? – ron