I have recently come across a code that looks similar to the following.
The question I want to ask is what would be the possible purposes of the Second's type parameters(namely the first type parameter) specified when being extended by the case classes.
I do not see any particular reason to use A
, Option[A]
and Seq[A]
as the type parameters are narrowed down by the extending case classes by [A <: SomeTrait, B <: AnotherTrait]
.
Am I missing any important points?
sealed trait Top[A, B]
sealed trait Second[A, B] extends Top[A, B]
case class ThirdA[A <: SomeTrait, B <: AnotherTrait](
returnType: Class[A],
relation: B
) extends Second[A, B]
case class ThirdB[A <: SomeTrait, B <: AnotherTrait](
returnType: Class[A],
relation: B
) extends Second[Option[A], B]
case class ThirdC[A <: SomeTrait, B <: AnotherTrait](
returnType: Class[A],
relation: B
) extends Second[Seq[A], B]
Following your logic
I mean what would the type parameters
A
,Option[A]
andSeq[A]
be trying to achieve(enforce) here? My understanding is that using OnlyA
is the same here as long as theSecond
is empty.
this standard GADT
// data Lam :: * -> * where
// Lift :: a -> Lam a -- ^ lifted value
// Pair :: Lam a -> Lam b -> Lam (a, b) -- ^ product
// Lam :: (Lam a -> Lam b) -> Lam (a -> b) -- ^ lambda abstraction
// App :: Lam (a -> b) -> Lam a -> Lam b -- ^ function application
// Fix :: Lam (a -> a) -> Lam a -- ^ fixed point
sealed trait Lam[A]
case class Lift[A](a: A) extends Lam[A]
case class Pair[A, B](la: Lam[A], lb: Lam[B]) extends Lam[(A, B)]
case class LamC[A, B](f: Lam[A] => Lam[B]) extends Lam[A => B]
case class App[A, B](f: Lam[A => B], la: Lam[A]) extends Lam[B]
case class Fix[A](f: Lam[A => A]) extends Lam[A]
doesn't make sense because Lift[A]
can be obtained as new Lam[A] {}
, Pair[A, B]
as new Lam[(A, B)] {}
, LamC[A, B]
as new Lam[A => B]
, App[A, B]
as new Lam[B] {}
, Fix[A]
as new Lam[A] {}
, and moreover App[X, A]
is the same as Fix[A]
:)
Well, yes, but objects of those types can be obtained having different objects firstly. For Lam[A]
you need an A
, for Pair[A, B]
you need a Lam[A]
and Lam[B]
etc.
Similarly, yes, ThirdB[A, B]
is ThirdA[Option[A], B]
and ThirdC
is ThirdA[Seq[A], B]
. But to have objects of those types you need to have different objects firstly. In order to have ThirdA[A, B]
you need objects of types Class[A]
and B
, in order to have ThirdB[A, B]
through ThirdA[Option[A], B]
you need objects of types Class[Option[A]]
and B
but you can have ThirdB[A, B]
directly just via Class[A]
and B
, in order to have ThirdC[A, B]
through ThirdA[Seq[A], B]
you need objects of types Class[Seq[A]]
and B
but you can have ThirdC[A, B]
directly just via Class[A]
and B
.
For example you can match on ThirdA
, ThirdB
, ThirdC
and write some logic depending on type. So you can specify your general logic for Option
and Seq
.
So actually this depends on what SomeTrait
, AnotherTrait
, Class
are.