Question

Dans Scala, la classe PartialFunction[A, B] est dérivée à partir du type Function[A, B] (voir Scala Référence, 12.3.3). Cependant, cela semble contre-intuitif pour moi, car un Function (qui doit être défini pour tous A) a des exigences plus strictes que PartialFunction, qui peut être indéfini à certains endroits.

Le problème que je suis tombé sur était que lorsque j'ai une fonction partielle, je ne peux pas utiliser Function pour étendre la fonction partielle. Par exemple. Je ne peux pas faire:

(pf orElse (_)=>"default")(x)

(Hope la syntaxe est au moins à distance à droite)

Pourquoi est-ce sous-typage fait inverse? Y a-t-il des raisons que j'ai négligé, comme le fait que les types de Function sont intégrés?

BTW, ce serait aussi bien si Function1 :> Function0 donc je ne doit pas avoir l'argument factice dans l'exemple ci-dessus: -)

Modifier pour clarifier le problème de sous-typage

La différence entre les deux approches peut souligner en examinant deux exemples. Lequel d'entre eux a raison?

One:

val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?

Deux:

def foo(f : (Int)=>Int) {
  print(f(1))
}
val bar = new PartialFunction[Int, Int] {
  def apply(x : Int) = x/2
  def isDefinedAt(x : Int) = x%2 == 0
}
foo(bar) // should this be a breach of promise?

Pas de solution correcte

Autres conseils

Parce que Scala (comme dans une langue complète Turing) il n'y a aucune garantie qu'une fonction est totale.

val f = {x : Int => 1 / x}

Cette fonction n'est pas définie à 0. Une fonction partielle est juste une fonction qui promet de vous dire où il est pas défini. Pourtant, Scala rend assez facile à faire ce que vous voulez

def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)}

val pf : PartialFunction[Int, String] = {case 1 => "one"} 

val g = pf orElse func2Partial{_ : Int => "default"}

scala> g(1)
res0: String = one

scala> g(2)
res1: String = default

Si vous préférez, vous pouvez faire func2Partial implicite.

PartialFunction a des méthodes qui ne Function1, il est donc le sous-type. Ces méthodes sont isDefinedAt et orElse.

Votre vrai problème est que PartialFunctions ne sont pas inférées parfois quand vous voulez vraiment comme eux d'être. Je suis plein d'espoir qui sera abordé à une date ultérieure. Par exemple, cela ne fonctionne pas:

scala> val pf: PartialFunction[String, String] = { case "a" => "foo" }
pf: PartialFunction[String,String] = <function>

scala> pf orElse { case x => "default" }
<console>:6: error: missing parameter type for expanded function 
((x0$1) => x0$1 match { case (x @ _) => "default" })

Mais cela ne:

scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>

Bien sûr, vous pouvez toujours faire ceci:

scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] = 
  new PartialFunction[T,R] { 
    def apply(x: T) = f(x)
    def isDefinedAt(x: T) = true 
  }
f2pf: [T,R](f: (T) => R)PartialFunction[T,R]

Et maintenant, il est plus comme vous voulez:

scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>

scala> println(res7("a") + " " + res7("quux"))
foo default
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top