有没有办法表达Scala中任何函数的反函数?
例如,如果我有这样的函数f
:
(x: Int) => x + 1
我希望能够编写反函数g
,如:
(f(x): Int) => x // not a valid scala syntax
或
(x: Int) => inverse(f(x)) // inverse would return (x => x -1)
你知道在Scala中做这种事情的方法吗?
N.B:x => x+1
仅供参考。我正在寻找一种解决此类任务的通用方法。
答案 0 :(得分:15)
不,这样的事情是不可能的。问题是并非所有数学函数都有反转。来自inverse functions上的维基百科条目:
并非所有功能都有反转。为了适用这个规则,每个元素y∈Y必须对应不超过一个x∈X;具有此属性的函数f被称为一对一,或信息保留或注入。
例如,平方根(sqrt
)函数只有在x^2
时才是平方函数(x >= 0
)的倒数,其中平方根函数是一对一的。我们可以说平方根函数的负数是x < 0
时的平方函数的倒数,只是因为x^2 = (-x)^2
。但这是square函数的一个特殊属性,一般来说肯定不正确。
答案 1 :(得分:2)
根据您的使用场景,您可以通过维护(Function, Result) => Arguments
的映射来执行此操作,然后调用inverse(f, r)
等方法,该方法返回存储在映射中的参数。但是,这只适用于1)如果在需要反向值之前调用原始函数,2)如果原始函数是单射的(如ddk已指出)。
还涉及相当多的实现开销(例如,您可能需要Function1
到Function22
的专用映射),特别是如果您想减少强加于函数实现者的样板代码量。 Aspect-oriented programming可以在此处提供帮助,类似于EJB3's Interceptors的注释也可能有用。
看起来,好像使用场景必须是一个非常特殊的场景来证明你必须跳过的所有篮球。
答案 2 :(得分:2)
你不能表达一个函数的逆,但你可以表达其结果的倒数,也许这可能适合你。
当您传递函数时,这非常有用。
例如,如果你有一个函数f: Int => Boolean
,你在高阶函数中使用它作为参数,你可以将它包装在同一类型x => !f(x)
的另一个函数中,它只返回计算结果的倒数:
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)
注意:不推荐使用班级remove
中的方法List
而应使用filterNot
,但我认为在此示例中remove
只是读得更好。
答案 3 :(得分:1)
从实用主义的角度来看,unapply
方法可用于表示反函数:
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)
答案 4 :(得分:0)
我正在添加一个答案,因为another question被标记为此副本的副本,似乎没有人提到这一点:理论上 可能自动计算&#34;反向&#34; (从某种意义上说,它对输入执行穷举搜索,并且在无限的二进制数字序列中回答&#34;无&#34;如果在有限的时间内没有解决方案):请参阅文章{{ 3}}(虽然它使用Haskell,而不是Scala)。
这种详尽搜索的实用效用当然是另一回事。