#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
orMonoid
, на которую он может ссылаться здесь, это обычная реализация, которую вы можете найти вscalaz
orcats
.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)
но в этом случае вы могли бы также явно объявить неявные параметры, как я упоминал.