Scala PartialFunctions от конкретных

Есть ли быстрый способ использовать в качестве конкретной функции (типа, скажем, (A) => B) как PartialFunction[A, B]? Самый краткий синтаксис, который я знаю:

(a: A) => a match { case obj => func(obj) }

Есть ли неявное преобразование где-нибудь, что-то вроде:

implicit def funcAsPartial[A, B](func: A => B) = new PartialFunction[A, B] {

  def isDefinedAt(a: A) = true
  def apply(a: A) = func(a)

}

Наверное, я только что написал то, что искал, но существует ли это уже в библиотеках Scala?

2 ответа

Решение

Делать это с неявным преобразованием опасно по той же причине, что (A) => B не должен наследовать от PartialFunction[A, B], То есть контракт PartialFunction гарантирует, что вы можете безопасно * позвонить apply где бы isDefinedAt возвращается true, Контракт Function1 не предоставляет такой гарантии.

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

implicit def funcAsPartial[A, B](f: A => B) = new {
   /** only use if `f` is defined everywhere */
   def asPartial(): PartialFunction[A, B] = {
      case a => f(a)
   }

   def asPartial(isDefinedAt: A => Boolean): PartialFunction[A, B] = {
      case a if isDefinedAt(a) => f(a)
   }
}

// now you can write
val f = (i: Int) => i * i

val p = f.asPartial // defined on all integers
val p2 = f.asPartial(_ > 0) // defined only on positive integers

* Как обсуждалось в комментариях, может быть не совсем понятно, что означает здесь "безопасность". Я думаю об этом, что PartialFunction явно объявляет свой домен в следующем точном смысле: если isDefinedAt возвращает true для значения x, затем apply(x) может быть оценена способом, который согласуется с намерением автора функции. Это не значит, что apply(x) не будет выбрасывать исключение, но просто, чтобы исключение было частью дизайна функции (и должно быть задокументировано).

Нет, я пытался найти один несколько месяцев назад и в итоге написал свой, который по сути такой же, как и ваш.

Другие вопросы по тегам