Type signature restriction for left and right

Given the following AST for Success and Failure :

 sealed trait Success case object FooGood extends Success case object BarGood extends Success sealed trait Failure case object FooBad extends Failure case object BarBad extends Failure 

And the method signature:

 def go[A <: Failure, B <: Success](x: Int): Either[A, B] = ??? 

However, I would like to restrict the Left and Right types to specific to Foo or Bar .

But the following code compiles (against my wishes):

 scala> go[FooBad.type, BarGood.type](5) scala.NotImplementedError: an implementation is missing 

How can I achieve this limit at compile time?

+5
source share
3 answers

It uses a solution based on a type class. It should be noted that for each (pair) AST node, it is not necessary to manually define instances of a class of a new type. This implies the introduction of a common super-type for each pair (although technically use it as a base class, it is just used as a tag type).

 sealed trait Success[T] abstract sealed class Foo abstract sealed class Bar case object FooGood extends Foo with Success[Foo] case object BarGood extends Bar with Success[Bar] sealed trait Failure[T] case object FooBad extends Foo with Failure[Foo] case object BarBad extends Bar with Failure[Bar] @annotation.implicitNotFound("Expecting reciprocal Failure and Success alternatives, but got ${A} and ${B}") trait IsGoodAndBadFacet[A,B] implicit def isGoodAndBadFacet[T,A,B](implicit e1: A <:< Failure[T], e2: B<:<Success[T]): IsGoodAndBadFacet[A,B] = null def go[A, B](x: Int)(implicit e: IsGoodAndBadFacet[A,B]): Either[A, B] = ??? 

Compliance Check:

 scala> go[FooBad.type, BarGood.type](5) <console>:17: error: Expecting reciprocal Failure and Success alternatives, but got FooBad.type and BarGood.type go[FooBad.type, BarGood.type](5) ^ scala> go[FooBad.type, FooGood.type](5) scala.NotImplementedError: an implementation is missing at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225) at .go(<console>:11) ... 33 elided scala> go[BarBad.type, BarGood.type](5) scala.NotImplementedError: an implementation is missing at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225) at .go(<console>:11) ... 33 elided 
+4
source

The problem is that the compiler does not know that FooGood somehow related to FooBad , so you need to hint somehow.

Here is what I came up with, although I admit that it is not very elegant:

 trait Grouping[B, G] object FooHelper { implicit object fooGrouping Grouping[FooBad.type, FooGood.type] } object BarHelper { implicit object barGrouping Grouping[BarBad.type, BarGood.type] } def go[A <: Failure, B <: Success](x: Int)(implicit ev: Grouping[A, B]): Either[A, B] = ??? import FooHelper._ import BarHelper._ // the following two type check go[FooBad.type, FooGood.type](5) go[BarBad.type, BarGood.type](5) // while these two do not go[FooBad.type, BarGood.type](5) go[BarBad.type, FooGood.type](5) 

As you can see, the tooltip is implemented by creating Grouping and putting the correct groupings in an implicit area. The problem with this approach is that the user can create their own groups, which may be invalid.

+2
source

You can limit the type of output to a Success / Failure pair by entering a type parameter:

 sealed trait Success[T] sealed trait Failure[T] sealed trait Foo sealed trait Bar case object FooGood extends Success[Foo] case object BarGood extends Success[Bar] case object FooBad extends Failure[Foo] case object BarBad extends Failure[Bar] def go[T, A <: Failure[T], B <: Success[T]](x: Int): Either[A, B] = ??? 

But! This only makes sense if you create a specific implementation that provides type T , because it is pointless to create such a signature in another way.

I can see any utility for this as part of the interface that holds back the go result, for example:

 trait Paired[T] { type A <: Failure[T] type B <: Success[T] def go(x: Int): Either[A, B] } 

If you want to explicitly specify types (but how will you create an implementation for this?) - the answer with the provision of implicit grouping is very reasonable.

0
source

All Articles