Что не так с определением метода

#scala #traversal #applicative #monoids

#scala #обход #аппликативный #моноиды

Вопрос:

Ниже приведены сигнатуры и определения моих методов в scala

   def accumulate[T[_]: Traversable, O: Monoid, A]: (A => O) => T[A] => O =
    fao => ta =>
      (implicitly[Traversable[T]].traverse[({type f[X] = Acc[O, X]})#f, A, O](ta)(a => Acc(fao(a)))).value

  def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = to => accumulate[T, O, O](a => a)(to)
  

Однако я получаю следующую ошибку для моего определения reduce

 Error:(160, 82) not enough arguments for method accumulate: (implicit evidence$7: Traversable[T], implicit evidence$8: Monoid[O])(O => O) => (T[O] => O).
Unspecified value parameter evidence$8.
  def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = to => accumulate[T, O, O](a => a)(to)
                                                                                 ^
  

Не уверен, где я ошибаюсь. Буду признателен за любую помощь.

Спасибо!

Комментарии:

1. Было бы проще, если бы вы предоставили ссылку на реализации Traversable / Monoid / Acc, afaik, встроенный в traversable scala, не имеет метода обхода, хотя класс типа обхода как в scalaz, так и в cats есть.

2. @AngeloGenovese можно с уверенностью предположить, что существует только одна (законная) реализация Traversable or Monoid , на которую он может ссылаться здесь, это обычная реализация, которую вы можете найти в scalaz or cats .

3. @Yawar справедливо, но это также означает, что для того, чтобы попытаться воспроизвести его проблему, я потратил время на выяснение того, как выглядел Acc, и вспомнил, что проходимые коллекции scala — это не то же самое, что класс типа обхода. Как ни странно, используя cats и фиктивный impl Acc, я не получаю ту же ошибку компиляции в scala 2.10. (вычеркните это, просто моя IDE скрывает от меня вещи)

4. @AngeloGenovese Компилятор жалуется, когда я добавляю определение reduce, когда я вынимаю компиляцию кода reduce, поэтому не уверен, что знание impl для traversable / monoid / acc предоставит дополнительную информацию в этом случае. Дайте мне знать, если вы все еще хотите, чтобы я добавил их, и я смогу добавить их тогда.

Ответ №1:

Вас сбивают с толку скрытые (неявные) параметры accumulate метода. Ограничения контекста, которые вы наложили на него, означают, что метод действительно имеет следующую сигнатуру типа:

 def accumulate[T[_], O, A](
  implicit traversable: Traversable[T],
  monoid: Monoid[O]): (A => O) => T[A] => O
  

На самом деле я бы посоветовал вам не использовать границы контекста, если вам действительно нужно использовать их соответствующие имплициты в ваших методах (в отличие от простой неявной передачи их в другой метод). Гораздо понятнее явно ввести импликации (по иронии судьбы).

Итак, что происходит в reduce , так это то, что вы пытаетесь передать функцию a => a в позиции, где компилятор ожидает два неявных аргумента Traversable[T] и Monoid[O] . Решение состоит в том, чтобы либо передать имплициты явно, либо мономорфизировать accumulate перед его вызовом:

 def reduce[T[_]: Traversable, O: Monoid]: T[O] => O = { to =>
  // This forces the compiler to pass in the correct implicits
  val accumulate_ = accumulate[T, O, O]
  accumulate_(a => a)(to)
}
  

Комментарии:

1. Спасибо! Это работает. Но почему это не сработало бы accumulate(Проходимый [T], моноидный [O])(a => a) (to) также из того, что вы написали. Это выдает ошибку компиляции.

2. @AbdulRahman хм, может быть, Traversable.apply и Monoid.apply не определены для возврата правильных импликаций? Можете ли вы опубликовать сообщение об ошибке компиляции?

3. Ошибка: (162, 27) объект, который можно обойти, не принимает параметры типа. ошибка accumulate(Проходимый[T], моноид[O])(a => a)(to):(162, 38) объект Monoid не принимает параметры типа. накапливать(проходимый [T], моноидный [O])(a => a)(to) ^

4. @AbdulRahman да, so Traversable.apply и Monoid.apply определенно не определены. Этот синтаксис сработал бы, если бы они были. В противном случае вам нужно будет сделать accumulate(implicitly[Traversable[T]], implicitly[Monoid[O]])(a => a)(to) но в этом случае вы могли бы также явно объявить неявные параметры, как я упоминал.