Почему это частичная функция <:Функция в Scala?

StackOverflow https://stackoverflow.com/questions/930698

  •  06-09-2019
  •  | 
  •  

Вопрос

В Scala PartialFunction[A, B] класс является производным от типа Function[A, B] (смотрите ссылку на Scala, 12.3.3).Однако мне это кажется нелогичным, поскольку Function (который должен быть определен для всех A) предъявляет более строгие требования, чем PartialFunction, который в некоторых местах может быть неопределенным.

Проблема, с которой я столкнулся, заключалась в том, что когда у меня есть частичная функция, я не могу использовать Function чтобы расширить частичную функцию.Например.Я не могу этого сделать:

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

(Надеюсь, синтаксис хотя бы отдаленно правильный)

Почему этот подтип выполняется в обратном порядке?Есть ли какие-то причины, которые я упустил из виду, например, тот факт, что Function типы встроены?

Кстати, было бы также неплохо, если бы Function1 :> Function0 так что мне не нужен фиктивный аргумент в приведенном выше примере :-)

Отредактируйте, чтобы прояснить проблему с подтипированием

Разницу между этими двумя подходами можно подчеркнуть, рассмотрев два примера.Кто из них прав?

Один:

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

Два:

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?

Нет правильного решения

Другие советы

Потому что в Scala (как и в любом языке, полном по Тьюрингу) нет гарантии, что функция является полной.

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

Эта функция не определена в 0.Частичная функция - это просто функция, которая обещает сообщить вам, где она не определена.Тем не менее, Scala позволяет достаточно легко делать то, что вы хотите

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

Если вы предпочитаете, вы можете сделать func2Partial неявным.

PartialFunction имеет методы, которые Function1 не имеет, следовательно, это подтип.Этими методами являются isDefinedAt и orElse.

Ваша настоящая проблема заключается в том, что PartialFunctionиногда они не выводятся, когда вам бы действительно этого хотелось.Я надеюсь, что этот вопрос будет решен в будущем.Например, это не работает:

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" })

Но это делает:

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

Конечно, вы всегда могли бы это сделать:

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]

И теперь это больше похоже на то, чего ты хочешь:

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

scala> println(res7("a") + " " + res7("quux"))
foo default
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top