Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In pure functional languages, is there an algorithm to get the inverse function?

In pure functional languages like Haskell, is there an algorithm to get the inverse of a function, (edit) when it is bijective? And is there a specific way to program your function so it is?

like image 867
MaiaVictor Avatar asked Nov 15 '12 18:11

MaiaVictor


People also ask

How do you find the inverse of a functional function?

How do you find the inverse of a function? To find the inverse of a function, write the function y as a function of x i.e. y = f(x) and then solve for x as a function of y.

Is there an inverse function in Python?

invert() in Python. numpy. invert() function is used to Compute the bit-wise Inversion of an array element-wise.

What is the purest functional programming language?

By this definition, Haskell, Mercury, Clean etc are pure functional languages; whereas Scala, Clojure, F#, OCaml etc are impure ones.


2 Answers

In some cases, yes! There's a beautiful paper called Bidirectionalization for Free! which discusses a few cases -- when your function is sufficiently polymorphic -- where it is possible, completely automatically to derive an inverse function. (It also discusses what makes the problem hard when the functions are not polymorphic.)

What you get out in the case your function is invertible is the inverse (with a spurious input); in other cases, you get a function which tries to "merge" an old input value and a new output value.

like image 103
Daniel Wagner Avatar answered Sep 21 '22 21:09

Daniel Wagner


No, it's not possible in general.

Proof: consider bijective functions of type

type F = [Bit] -> [Bit] 

with

data Bit = B0 | B1 

Assume we have an inverter inv :: F -> F such that inv f . f ≡ id. Say we have tested it for the function f = id, by confirming that

inv f (repeat B0) -> (B0 : ls) 

Since this first B0 in the output must have come after some finite time, we have an upper bound n on both the depth to which inv had actually evaluated our test input to obtain this result, as well as the number of times it can have called f. Define now a family of functions

g j (B1 : B0 : ... (n+j times) ... B0 : ls)    = B0 : ... (n+j times) ... B0 : B1 : ls g j (B0 : ... (n+j times) ... B0 : B1 : ls)    = B1 : B0 : ... (n+j times) ... B0 : ls g j l = l 

Clearly, for all 0<j≤n, g j is a bijection, in fact self-inverse. So we should be able to confirm

inv (g j) (replicate (n+j) B0 ++ B1 : repeat B0) -> (B1 : ls) 

but to fulfill this, inv (g j) would have needed to either

  • evaluate g j (B1 : repeat B0) to a depth of n+j > n
  • evaluate head $ g j l for at least n different lists matching replicate (n+j) B0 ++ B1 : ls

Up to that point, at least one of the g j is indistinguishable from f, and since inv f hadn't done either of these evaluations, inv could not possibly have told it apart – short of doing some runtime-measurements on its own, which is only possible in the IO Monad.

                                                                                                                                   ⬜

like image 23
leftaroundabout Avatar answered Sep 19 '22 21:09

leftaroundabout