4

企業も人もいます。ユーザーは、ビジネスについて「いいね!」したり、コメントを投稿したりできますが、同じことは個人には起こりません。ユーザーがビジネスについて何かを投稿したり、いいねtarget!

trait TargetingRelation[TargetingType[_],TargetedType]

class Business

class Person

class Post[Target | TargetingRelation[Business,Post] ] {
  def target:Target
}

class Like[Target | TargetingRelation[Business,Like] ] {
  def target:Target
}

ここで、あるプロパティを満たす(またはより多くの型の魅力を持つ)T | P[T]型パラメーターを意味する表記法を考案しています。コードのどこかで、次のような宣言が必要です。TP[T]T :|: P[T]

object canPostAboutBusiness extends TargetingRelation[Post,Business] 
object canLikeBusiness      extends TargetingRelation[Like,Business]

これらのオブジェクトは実際には証拠であり、Haskell 型クラスのようなものです。したがって、これはチェックを入力します:

val p = new Post[Business]
val l = new Like[Business]

しかし、これではありません

val p = new Post[Person]
val l = new Like[Person]

Scala に関する私の知識が許す限り、この特定の状況を満足のいく方法でモデル化することはできません。ビジネスは次のようなものではないため、これはサブタイピングではないと主張します。

class Business extends 
  TargetingRelation[Post,Business] with 
  TargetingRelation[Like,Business]

実際のところ、それは非常に望ましいことBusinessですPost. この関係は、実際には と の両方の外にPostありBusinessます。その上、上記のコードは2回Businessから継承しているため、そもそもコンパイルすらしないと思います。TargetingRelation洞察は大歓迎です。

related :クラス型パラメーターにバインドされたコンテキストを使用する

4

1 に答える 1

6

暗黙を使用して型クラスのように機能するものを使用して、scala でこれを行うことができます。例えば:

import scala.language.higherKinds

trait TargetingRelation[A[_], B]

class Business
class Person

// Using explicitly declared implicit parameter:
class Post[T](implicit ev: TargetingRelation[Post, T])

// Using a "context bound". The syntax is a little hairy and uses
// a type lambda because TargetingRelation takes multiple type params
class Like[T : ({type S[x] = TargetingRelation[Like, x]})#S]

implicit object canPostAboutBusiness extends TargetingRelation[Post,Business]
implicit object canLikeBusiness      extends TargetingRelation[Like,Business]

次に、クラスをインスタンス化できますBusiness

scala> val p = new Post[Business]
p: Post[Business] = Post@374c991a

scala> val l = new Like[Business]
l: Like[Business] = Like@1fd348f8

しかし、一緒ではありませんPerson

scala> val p1 = new Post[Person]
<console>:15: error: could not find implicit value for parameter ev: TargetingRelation[Post,Person]
       val p1 = new Post[Person]
                ^

scala> val p2 = new Like[Person]
<console>:15: error: could not find implicit value for evidence parameter of type TargetingRelation[Post,Person]
       val p2 = new Like[Person]
                ^

「scala typeclasses」から検索すると、これがどのように機能するかについての詳細な説明がたくさん見つかりますが、基本的には、コンストラクターが型の暗黙的なパラメーターを取り、TargetingRelation[TargetingType[_],TargetedType]その型の暗黙的なものをスコープに配置する必要があります。クラスを構築する(PostまたはLike)。暗黙的なものは、型クラスのインスタンスがあることの「証拠」として機能しTargetedTypeます (また、他の言語の型クラス実装で自動的に渡されるメソッドの明示的な辞書の役割を果たします)。

実際、scala にはContext Boundと呼ばれる、これを支援するためのシナティック シュガーがあります。これにより、次のように記述されたメソッドが発生します。

def a[A: B] = ???

に翻訳される

def a[A](implicit ev: B[A]) = ???

あなたの特定の例では、複数の型パラメーターがあるため、コンテキスト境界構文は少し扱いに​​くいですが、この SO の質問が説明しているように実行できます。

于 2013-12-07T07:55:33.633 に答える