1

... または、Scala をコーディングしなければならない Haskell プログラマーの事故、パート 5.

私はScalaで次の構造を持っています:

case class ResourceTree(
  resources: Map[String, ResourceTree]
) 

Semigroupそして、Cats を使用して、そのインスタンスを定義したいと思います。

object ResourceTreeInstances {
  implicit val semigroupInstance = new Semigroup[ResourceTree] {
    override def combine(x: ResourceTree, y: ResourceTree): ResourceTree = {
      ResourceTree(
        x.resources |+| y.resources
      )
    }
  }

これにより、次のエラーが発生します。

value |+| is not a member of Map[String, ResourceTree]
[error]  Note: implicit value semigroupInstance is not applicable here because it comes after the application point and it lacks an explicit result type
[error]         x.resources |+| y.resource

したがって、私の推測では、Scala コンパイラーのインスタンスを定義しているため、 ofSemigroupのインスタンスを派生させることはできません。次のインスタンスがコンパイルされているため、これは確認されているようです。SemigroupMap[String, ResourceTree]

implicit val semigroupInstance = new Semigroup[ResourceTree] {
  override def combine(x: ResourceTree, y: ResourceTree): ResourceTree = {
    dummyCombine(x, y)
  }
}

// FIXME: see if there's a better way to avoid the "no instance of Semigroup" problem
def dummyCombine(x: ResourceTree, y: ResourceTree): ResourceTree = {
  ResourceTree(
    x.resources |+| y.resources
  )
}

これが Scala でセミグループのインスタンスを定義する正しい方法である場合、この言語での FP の実行をあきらめるという考えを検討し始めるので、私が間違っていることを本当に望んでいます。

より良い方法はありますか?

4

1 に答える 1

4

以下は問題なく動作するはずです。

import cats.Semigroup
import cats.instances.map._
import cats.syntax.semigroup._

case class ResourceTree(resources: Map[String, ResourceTree]) 

implicit val resourceTreeSemigroup: Semigroup[ResourceTree] =
  new Semigroup[ResourceTree] {
    def combine(x: ResourceTree, y: ResourceTree): ResourceTree =
      ResourceTree(
        x.resources |+| y.resources
      )
  }

キーは、エラー メッセージのこの部分です:「明示的な結果の型がありません」。MapScala の再帰メソッドには明示的な戻り値の型が必要です。同様に、それ自体に依存する型クラス インスタンス (この場合はインスタンスや|+|構文などを介して直接的または間接的に) もそれらを必要とします。

一般に、すべての暗黙的な定義に明示的な戻り値の型を配置することをお勧めします。そうしないと、予期しない動作が発生する可能性があります。そのいくつかは、(この場合のように) 考えて仕様を読むと理解できます。コンパイラのバグのようです。

于 2016-09-21T16:39:55.573 に答える