Как объединить массивы моноидного типа?

Список или массив моноидов типа A тоже являются моноидами. Теперь я хотел бы combine массивы целых чисел, используя cats.

scala> 1 |+| 2
res1: Int = 3

scala> Array(1, 2, 3) |+| Array(1, 2, 3)
<console>:21: error: value |+| is not a member of Array[Int]
   Array(1, 2, 3) |+| Array(1, 2, 3)

Вместо этого я хотел бы получить Array(2, 4, 6) в результате Array(1, 2, 3) |+| Array(1, 2, 3). Как я могу это сделать ?


person Michael    schedule 07.03.2017    source источник
comment
|+| на самом деле не для этого. Это должна быть операция добавления. Что произойдет, если массивы будут разного размера?   -  person Michael Zajac    schedule 07.03.2017
comment
Список или массив моноида типа A тоже является моноидом это в теории, но на самом деле вам нужно указать Monoid[Array] в коде, например. через implicit.   -  person sebszyller    schedule 07.03.2017
comment
@MichaelZajac Спасибо. Я был, вероятно, неправ. Массив моноидов, вероятно, не является моноидом.   -  person Michael    schedule 07.03.2017
comment
Обратите внимание, что в Scalaz есть операция под названием merge, которая делает именно то, что вам нужно: github.com/scalaz/scalaz/blob/ Я думаю, они просто еще не портировали его на cats.   -  person ZhekaKozlov    schedule 13.03.2017
comment
@ЖекаКозлов О, спасибо. Хорошо знать. Я проверю, существует ли он в cats.   -  person Michael    schedule 13.03.2017
comment
@Michael Я уже проверил и не нашел :( Кроме того, я не нашел экземпляр Monoid для Array.   -  person ZhekaKozlov    schedule 13.03.2017
comment
Спасибо еще раз. Может, не портировали по какой-то причине...   -  person Michael    schedule 13.03.2017
comment
@Michael Действительно, я думаю, что сопровождающие приняли сознательное решение исключить его, поскольку он не является широко используемым типом коллекции в Scala.   -  person Michael Zajac    schedule 14.03.2017


Ответы (1)


combine на Seq или Array обычно означает добавление их для создания новой коллекции.

Однако вы можете сделать то, что пытаетесь сделать, определив свой собственный Monoid с zip вместо append. Вот что я придумал на лету:

implicit val zipArrayMonoid = new Monoid[Array[Int]] {
  override def combine(x: Array[Int], y: Array[Int]) = {
    x.zip(y).map {
      case (a, b) => a + b
    }
  }

  override def empty = Array.empty
}

Это приведет к тому, что дополнительные значения массивов разных размеров будут игнорироваться (как это делает реализация zip, вы можете проверить документы здесь)

Вот scalaFiddle с результатом: https://scalafiddle.io/sf/YzdUl4L/0

person Luka Jacobowitz    schedule 07.03.2017
comment
Спасибо ! но что, если массивы не одного размера? - person Michael; 07.03.2017
comment
Этот экземпляр нарушает все законы моноидов. - person drexin; 08.03.2017
comment
Это так, но я не вижу, как реализовать экземпляр Monoid для его варианта использования, не нарушая их. - person Luka Jacobowitz; 10.03.2017