Modeling a binary relationship between two types

Viewed 239

There are businesses and people. Users can either like or post a comment about a business but the same can not happen with a person. When a user posts something about a business or likes it, that business is called the target of that like or post:

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
}

Here I'm inventing a T | P[T] notation meaning type parameter T such that it satisfies some property P[T] (or T :|: P[T] if it carries more type-appeal). Somewhere else in the code I want to have declarations like:

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

these objects are evidences actually, something like Haskell type-classes. So this would type check:

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

but not this one:

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

As far as my knowledge of Scala permits, I can't model this particular state of affairs in a satisfactory way. Now I insist that this is not sub-typing because Business is not a:

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

As a matter of fact it is very desirable that Business remains totally ignorant of the Post. The relationship is actually outside of both Post and Business. Besides, I suppose the above code would not even compile to begin with since Business is inheriting from TargetingRelation twice. Insights are most welcome.

related : Using a context bound in a class type parameter

1 Answers
Related