Встроенная функция неоднозначности в Scala - PullRequest
0 голосов
/ 13 октября 2018

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

List(1,2,3).fold(1)(_ * _)

К вышесказанному я могу просто передать _ \* _

Однако, определив свою собственную игрушечную функцию zipWith () , мне нужно быть очень явным при передаче функции:

implicit class EnrichedList[A](val self: List[A]) extends AnyVal {
  def zipWith[B, C](that: List[B])
                   (implicit zipper: A => B => C): List[C] = {

    def zipWithHelper(zipper: A => B => C)
                     (as: List[A])
                     (bs: List[B]): List[C] = {
      (as, bs) match {
        case (_, Nil) => Nil
        case (Nil, _) => Nil
        case (a :: restOfA, b :: restOfB) =>
          zipper(a)(b) :: zipWithHelper(zipper)(restOfA)(restOfB)
      }
    }

    zipWithHelper(zipper)(self)(that)
  }
}

Это: List(1, 3, 4).zipWith(List(3, 4, 5))(_ * _) не будет работать, говоря:

Ошибка: (60, 46) отсутствует тип параметра для расширенной функции ((x $ 1:, x $ 2) =>x $ 1. $ times (x $ 2)) List (1, 3, 4) .zipWith (List (3, 4, 5)) (_ * _)

Мне нужно сказать, какой типаргументов функция принимает:

List(1, 3, 4).zipWith(List(3, 4, 5))((x: Int) => (y: Int) => x * y)

Почему компилятор не позволяет мне просто передать сокращенную версию _ * _?

1 Ответ

0 голосов
/ 13 октября 2018

Выражение _ * _ не является сокращением для (x: Int) => (y: Int) => x * y.Это сокращение для (x: Int, y: Int) => x * y.Если вы измените тип zipper на (A, B) => C вместо A => B => C, он должен работать. Curry это вещь, это не просто причудливое имя для функции идентификации.

Здесь компилируется:

implicit class EnrichedList[A](val self: List[A]) {
  def zipWith[B, C](that: List[B])
                   (implicit zipper: (A, B) => C): List[C] = {

    def zipWithHelper(zipper: (A, B) => C)
                     (as: List[A])
                     (bs: List[B]): List[C] = {
      (as, bs) match {
        case (_, Nil) => Nil
        case (Nil, _) => Nil
        case (a :: restOfA, b :: restOfB) =>
          zipper(a, b) :: zipWithHelper(zipper)(restOfA)(restOfB)
      }
    }

    zipWithHelper(zipper)(self)(that)
  }
}

println( List(1, 3, 4).zipWith(List(3, 4, 5))(_ * _) )

и печатается

List(3, 12, 20)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...