2012-09-27 15 views
5

Esiste un modo per esprimere l'inverso di qualsiasi funzione in scala?Funzione inversa in Scala

Per esempio se ho una funzione f simili

(x: Int) => x + 1

Vorrei poter scrivere una funzione inversa g come

(f (x): Int) sintassi => x // non una valida scala

o

(x: Int) => inversa (f (x)) // inversa sarebbe tornato (x => x -1)

Sai un modo per fare questo tipo di cosa in scala?

NB = x => x + 1 è solo per l'esempio che sto cercando un modo generico per risolvere questo tipo di compito

Grazie!

+7

Non è necessaria la funzione di inversione per questo esercizio, pensare alla definizione matematica di esistere: Mappa (S, f) = b | Esiste c € S, f (c) = b. –

+0

cosa dire creare la propria InvertibleFunction [Int, Int] – Edmondo1984

risposta

14

No, qualcosa del genere non è possibile. Il problema è che non tutte le funzioni matematiche hanno inversioni. Dalla voce di Wikipedia su inverse functions:

Non tutte le funzioni hanno un inverso. Affinché questa regola sia applicabile, ciascun elemento y ∈ Y deve corrispondere a non più di uno x ∈ X; una funzione ƒ con questa proprietà è chiamata one-to-one, o information-preserving, o un'iniezione.

Ad esempio, la radice quadrata (sqrt) funzione è l'inverso della funzione quadrato (x^2) solo quando x >= 0, dove la funzione radice quadrata è uno-a-uno. Possiamo dire che il negativo della funzione radice quadrata è l'inverso della funzione quadrata quando x < 0 solo perché x^2 = (-x)^2. Ma questa è una proprietà speciale della funzione quadrata e non è certamente vera in generale.

+1

grazie, temevo che non fosse possibile, ora è confermato :) – Loic

+1

Come nota aggiuntiva, le funzioni che sono strettamente reversibili sono chiamate 'Bijections'. – christopher

2

A seconda dello scenario di utilizzo, è possibile eseguire questa operazione mantenendo una mappa da (Function, Result) => Arguments e quindi chiamare un metodo come inverse(f, r) che restituisce gli argomenti memorizzati nella mappa. Tuttavia, questo funziona solo 1) se la funzione originale è invocata prima che sia necessario il valore inverso e 2) se la funzione originale è iniettiva (come già rilevato da ddk).

C'è anche un po 'di overhead di implementazione (per esempio, probabilmente è necessaria una mappa dedicata per Function1 a Function22), soprattutto se si vuole ridurre la quantità di codice boilerplate imposto sugli implementatori di funzioni. Aspect-oriented programming potrebbe aiutare qui, potrebbero anche funzionare annotazioni simili a EJB3's Interceptors.

Sembra, tuttavia, come se lo scenario di utilizzo dovesse essere abbastanza speciale da giustificare tutti i cerchi da superare.

2

Non è possibile esprimere l'inverso di una funzione, ma è possibile esprimere l'inverso del suo risultato e forse ciò sarebbe opportuno.

Questo può essere utile quando si passa la funzione in giro.

Ad esempio, se si dispone di una funzione f: Int => Boolean che si sta utilizzando come parametro in una funzione di ordine superiore, si può avvolgere in un'altra funzione dello stesso tipo x => !f(x) che justs restituisce l'inverso del risultato calcolato:

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: il metodo remove in classe List è deprecato e filterNot dovrebbe essere usato al posto, ma credo che in questo esempio remove solo legge meglio.

1

Dal punto di vista pragmatistica, unapply metodo potrebbe essere utilizzato per rappresentare funzioni inverse:

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

Questo è sia orribile che interessante. –

0

sto aggiungendo una risposta a causa della another question contrassegnato come un duplicato di questo, e nessuno sembra aver ancora parlato di questo: è teoricamente possibile calcolare automaticamente "l'inverso" (nel senso che esegue una ricerca esauriente sull'input e risponde "nessuno" se non c'è soluzione, entro un tempo limitato) di funzioni su infinito sequenze di cifre binarie: vedere l'articolo "Seemingly impossible functional programs" (sebbene usi Haskell, non Scala).

L'utilità di questa ricerca esauriente è un'altra questione, ovviamente.