功能平等概念

时间:2013-12-05 02:32:54

标签: scala

Scala中是否存在函数相等的概念?

scala> def foo(x: Int) = x + 1
foo: (x: Int)Int

scala> def bar(x: Int) = x + 1
bar: (x: Int)Int

所以我无法在函数上调用==

scala> foo == bar
<console>:10: error: missing arguments for method foo;
follow this method with `_' if you want to treat it as a partially applied
 function
              foo == bar
              ^

除了验证所有 x foo(x) == bar(x)(不知道该怎么做)之外,我还能如何验证相等性?

5 个答案:

答案 0 :(得分:5)

你真的不希望==产生除false之外的任何内容,因为==表示“具有相同的内存地址”,除非它是专门为该类定义的。毕竟,

scala> class A
scala> (new A) == (new A)
res0: Boolean = false

如果Function1尝试提供==的实施,则不清楚它会检查什么。所有可能的投入都有相同的结果同样的行为?相同的字节代码?

如果你想要一个具有良好定义的相等操作的函数类,你必须自己编写它:

class Adder(private val toAdd: Int) extends (Int => Int) {
  override def apply(n: Int) = n + toAdd

  override def equals(other: Any) = other match {
    case o: Adder => this.toAdd == o.toAdd
    case _ => false
  }
}

然后你可以这样做:

scala> val foo = new Adder(1)
foo: Adder = <function1>

scala> val bar = new Adder(1)
bar: Adder = <function1>

scala> foo(2)
res4: Int = 3

scala> foo == bar
res5: Boolean = true

要获得更简单的解决方案,只需将您的课程设为case class,即可免费提供equalshashCode个实施:

case class Adder(private val toAdd: Int) extends (Int => Int) {
  override def apply(n: Int) = n + toAdd
}

答案 1 :(得分:2)

假设存在这样的功能。

/** Decides whether `f1` and `f2` compute the same function. */
def functionEquals[A, B](f1: A => B, f2: A => B): Boolean

然后我们可以写下这个:

/** Decides whether `m` halts on input `x`. */
def halts[X](m: X => Unit, x: X): Boolean = 
  !functionEquals[Unit, Unit](
    { _ => while(true)() },
    { _ => m(x) }
  )

当然,这是不可能的。

答案 2 :(得分:1)

首先,在可以计算的函数上没有一般的相等关系(因为函数本质上是无限集)。根据函数的表示,您可能会获得弱相等性(即,当结果为true时两个参数相等但在结果为false时它们也可能相等)。

在scala中你可能会这样做:

scala> (foo _).equals((bar _ ))
res3: Boolean = false

scala> (foo _) == ((foo _ ))
res5: Boolean = false

函数背后的下划线是区分零参数应用程序和函数值的语法要求。 equals方法(作为==)是一般对象相等,因此只是一个by-reference比较。每个评估都会产生一个新的引用(闭包实例)。所以平等很弱:

scala> val x = foo _
x: Int => Int = <function1>

scala> x.equals(x)
res7: Boolean = true

答案 3 :(得分:1)

  

Scala中是否存在函数相等的概念?

简短而有些无益的答案是否定的,你不能写下因赖斯定理而导致的函数的一般情况平等。推断两个函数是否相等需要证明函数中的逻辑,这可以在某些情况下完成,但不是一般的。

作为一个愚蠢的例子,考虑到这样一个事实:我们知道任何偶数(可表示为2 * n)数模2都会留下零余数,这是小学数学的微不足道的结果,但它是编译器需要的一段知识。必须假设foo == bar。

def foo(x: Int) = (x*2) % 2
def bar(x: Int) = 0

Scala的类型系统可以使用更复杂的类型编码其中一些属性,但通常不会。

答案 4 :(得分:1)

TLDR:是的,有功能平等的概念。但它是基本的对象引用平等,因此效益很小

  • 问题1:您可以在函数值上调用== - 但defs不是val。

    你不能在defs上调用任何方法(除了函数应用程序的特殊情况) - 因为它们不是对象实例(vals)。但你可以通过调用它们(应用)将它们转换为val,为缺少的参数指定_(创建部分应用的函数):

    val fooVal = foo(_)  // type is Function1[Int, Int] (from def foo = ...)
    val barVal = bar(_)  // ditto
    
    fooVal == barVal  // == works (returns false)
    foo(_) == bar(_)  // ditto
    
  • 问题2:Function1没有定义equals()覆盖

    Function1定义不会覆盖equalshttps://github.com/scala/scala/tree/v2.10.3/src/library/scala/Function1.scala#L1Function1扩展AnyRef,从而继承== / equals / eq的功能:

    • Any.==只需委托Any.equals
    • AnyRef.equals只需委托AnyRef.eq,即检查对象引用的等效性。

    因此,Function1。==表示函数对象(val)引用的等价:

    val fooVal = foo(_) 
    val foo2Val = foo(_)
    val foo3Val = fooVal
    val barVal = bar(_) 
    
    fooVal == barVal // returns false
    fooVal == foo2Val // returns false (different objects)
    fooVal == foo3Val // returns true (same object) 
    
  • 问题3:当然,您可以延长Function1 - 但是如何定义有意义的equals ???

    abstract class MyFunction1[A,B] extends Function1[A,B] {
      // abstract because apply needs to be defined later for each different function
    
      override def equals(other: Any) = 
        // your smart definition here!
    }
    
    val myDoIt1 = new MyFunction1[Int, Int] {
      def apply(x: Int): Int = x + 1
    }
    val myDoIt2 = new MyFunction1[Int, Int] {
      def apply(y: Int): Int = y + 2 -1
    }
    
    // What equals logic could make these two equate? 
    // Would need compilation smarts & logic matching! 
    // Fall-back to class comparison would only work with extensive code design restrictions.