Полугруппа с функцией в Scala - PullRequest
       71

Полугруппа с функцией в Scala

0 голосов
/ 14 сентября 2018

Я пытаюсь преобразовать Haskell Semigroup в Scala. Код на Haskell работает нормально, но я не могу написать его в Scala

Haskell:

import Data.Semigroup

newtype Combine a b = Combine { unCombine :: (a -> b) }

instance Semigroup b => Semigroup (Combine a b) where  
    Combine f <> Combine g = Combine (f <> g)

f = Combine $ \n -> Sum (n + 1)
g = Combine $ \n -> Sum (n - 1)

print (unCombine (f <> g) $ 0)   -- Sum 0
print (unCombine (f <> g) $ 10)  -- Sum 20

Скала код

import cats.Semigroup
import cats.instances.all._

trait Combine[A, B] {
    def unCombine(a: A): B
}

val f = new Combine[Int, Int] {
  override def unCombine(n: Int): Int = n + 1
}

val g = new Combine[Int, Int] {
  override def unCombine(n: Int): Int = n - 1
}


implicit val mySemigroup: Semigroup[Combine[Int, Int]] = new Semigroup[Combine[Int, Int]] {
  def combine(x: Combine[Int, Int], y: Combine[Int, Int]): Combine[Int, Int] = (x,y) match {
    // ???
  }
}

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

В дополнение к ответу @KartikSabharwal, поскольку и Semigroup, и Combine являются функциональными интерфейсами, начиная с Scala 2.12, вы можете определить конкретный случай следующим образом:

implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
  (x, y) => a => x.unCombine(a) + y.unCombine(a)

И общий случайТо, что упомянул @KartikSabharwal, будет выглядеть так в Scala 2.12:

// Don't forget to NOT import `cats.instances.all._` together with this import
import cats.implicits._ 

implicit def combineSemigroup[A, B](
  implicit ev: Semigroup[B]
): Semigroup[Combine[A, B]] =
  (x, y) => a => x.unCombine(a) combine y.unCombine(a)

И так в Scala 2.11:

import cats.implicits._ 

implicit def combineSemigroup[A, B](
  implicit ev: Semigroup[B]
): Semigroup[Combine[A, B]] =
  new Semigroup[Combine[A, B]] {
    override def combine(x: Combine[A, B], y: Combine[A, B]): Combine[A, B] =
      new Combine[A, B] {
        override def unCombine(a: A): B = x.unCombine(a) combine y.unCombine(a)
      }
  }
0 голосов
/ 14 сентября 2018

Вот код, который отвечает на ваш конкретный вопрос.

import cats.Semigroup
import cats.instances.all._

object Main extends App {

  trait Combine[A, B] {
    def unCombine(a: A): B
  }

  override def main(args: Array[String]): Unit = {
    implicit val mySemigroup: Semigroup[Combine[Int, Int]] =
      new Semigroup[Combine[Int, Int]] {
        def combine(x: Combine[Int, Int], y: Combine[Int, Int]): Combine[Int, Int] =
          new Combine[Int, Int] {
            override def unCombine(n: Int): Int =
              Semigroup[Int].combine(x.unCombine(n), y.unCombine(n))
          }
        }

    val f = new Combine[Int, Int] {
      override def unCombine(n: Int): Int = n + 1
    }

    val g = new Combine[Int, Int] {
      override def unCombine(n: Int): Int = n - 1
    }

    val example = Semigroup[Combine[Int, Int]].combine(f, g).unCombine(10)

    printf("%d\n", example)
  }
}

В идеале Я бы хотел продублировать код Haskell по духу и реализовать что-то в форме

// 'a' can be any type
// Semigroup[b] must exist
implicit val mySemigroup: Semigroup[Combine[a, b]] =
  def combine(x: Combine[a, b], y: Combine[a, b]): Combine[a, b] =
    new Combine[a, b] {
      override def unCombine(n: a): b =
        Semigroup[b].combine(x.unCombine(n), y.unCombine(n))
    }

Но я не знаю достаточно Scala, чтобы выполнить это.Я обновлю ответ, когда выясню, или кто-то другой может прийти и отредактировать этот ответ / опубликовать лучший.

...