2012-09-27 31 views
5

¿Hay una manera de expresar la inversa de cualquier función en Scala?función inversa en Scala

Por ejemplo si tengo una función f como este

(x: Int) => x + 1

me gustaría ser capaz de escribir una función inversa g como

(f (x): Int) sintaxis => x // no a Scala válido

o

(x: int) => inversa (f (x)) // inversa volvería (x => x -1)

¿Conoce una manera de hacer este tipo de cosa en Scala?

N.B = x => x + 1 es sólo para el ejemplo que estoy buscando una manera genérica para resolver este tipo de tareas

Gracias!

+7

No necesita la función inversa para este ejercicio, piense en la definición matemática de existir: Mapa (S, f) = b | Existe c € S, f (c) = b. –

+0

¿qué ocurre al crear su propia InvertibleFunction [Int, Int] – Edmondo1984

Respuesta

14

No, algo así como eso no es posible. El problema es que no todas las funciones matemáticas tienen inversos. Desde la entrada de Wikipedia en inverse functions:

No todas las funciones tienen una inversa. Para que esta regla sea aplicable, cada elemento y ∈ Y debe corresponder a no más de una x ∈ X; una función ƒ con esta propiedad se llama uno-a-uno, o preservación de la información, o una inyección.

Por ejemplo, la raíz cuadrada (sqrt) función es la inversa de la función cuadrado (x^2) sólo cuando x >= 0, donde la función de raíz cuadrada es uno-a-uno. Podemos decir que el negativo de la función raíz cuadrada es la inversa de la función cuadrado cuando x < 0 sólo porque x^2 = (-x)^2. Pero esa es una propiedad especial de la función cuadrada y ciertamente no es cierta en general.

+1

gracias, temía que no fuera posible, ahora está confirmado :) – Loic

+1

Como nota adicional, las funciones que son estrictamente reversibles se llaman 'Bijections'. – christopher

2

Dependiendo de su escenario de uso, puede hacer una especie de esto manteniendo un mapa de (Function, Result) => Arguments, y luego llamar a un método como inverse(f, r) que devuelve los argumentos almacenados en el mapa. Sin embargo, esto solo funciona 1) si se invoca la función original antes de que se necesite el valor inverso y 2) si la función original es inyectiva (como ya se señaló ddk).

También hay bastante sobrecarga de implementación involucrada (por ejemplo, probablemente necesite un mapa dedicado para Function1 a), especialmente si desea reducir la cantidad de código repetitivo impuesto a los implementadores de funciones. Aspect-oriented programming podría ayudar aquí, las anotaciones similares a EJB3's Interceptors también podrían funcionar.

Parece, sin embargo, como si el escenario de uso debe ser uno muy especial para justificar todos los aros que tiene que saltar a través.

2

Usted no puede expresar la inversa de una función, pero se puede expresar la inversa de su resultado y tal vez eso le conviene.

Esto puede ser útil cuando se pasa la función.

Por ejemplo, si tiene una función f: Int => Boolean que está utilizando como parámetro en una función de orden superior, se puede envolver en otra función del mismo tipo que x => !f(x) justs devuelve el inverso del resultado calculado:

def select(ls: List[String], p: String => Boolean): List[String] = 
    ls.remove(x => !p(x)) 
// select: (ls: List[String], p: String => Boolean)List[String] 

val li = List("one", "two", "three") 
// li: List[java.lang.String] = List(one, two, three) 

/* using select with some conditions */ 
select(li, _.length() > 3) // equivalent to select(li, x => x.length() > 3) 
// res0: List[String] = List(three) 
select(li, _.length() <= 3) // equivalent to select(li, x => x.length() <= 3) 
// res1: List[String] = List(one, two) 

/* using remove with the same conditions */ 
li.remove(_.length() > 3) // equivalent to li.remove(x => x.length() > 3) 
// res2: List[java.lang.String] = List(one, two) 
li.remove(_.length() <= 3) // equivalent to li.remove(x => x.length() <= 3) 
// res3: List[java.lang.String] = List(three) 

NOTA: remove método en la clase List es obsoleto y filterNot se debe utilizar en su lugar, pero creo que en este ejemplo remove simplemente lee mejor.

1

De vista pragmatista, unapply método podría ser utilizado para representar funciones inversas:

object f { 
    def apply(x: Int) = x + 1 
    def unapply(x: Int) = Some(x - 1); 
} 

val x = 1 
val f(y) = f(x) 

assert(x == y) 
+0

Esto es aterrador y genial. –

0

Estoy añadiendo una respuesta debido a another question marcado como duplicado de éste, y nadie parece haber mencionado esto todavía: es teóricamente posible calcular automáticamente el "inverso" (en el sentido de que realiza una búsqueda exhaustiva sobre la entrada, y responde "ninguno" si no hay solución, en un tiempo finito) de funciones sobre infinito secuencias de dígitos binarios: ver el artículo "Seemingly impossible functional programs" (aunque usa Haskell, no Scala).

Práctica utilidad de esta búsqueda exhaustiva es otra cuestión, por supuesto.