Scala type restrictions are not displayed correctly in the conformance statement

I have a case class that accepts arguments with a limited type, however, when using a case class extractor, the type system seems to lose boundaries and print "Any" instead.

For instance:

trait Expr[T]

case class IntLit(value:Int) extends Expr[Int]
case class GreaterThan[T <% Ordered[T]]( a:Expr[T], b:Expr[T] ) extends Expr[Boolean]

object TestRuntime {
    def execute[T]( expr:Expr[T] ):T = expr match {
        case IntLit(value)    => value

        // ---> This line fails because the compiler thinks a and b are Expr[Any]
        //      Instead of Expr[_ <% Ordered[_]]
        //      error: value > is not a member of Any
        case GreaterThan(a,b) => execute(a) > execute(b) 

        // ---> Whereas this line works correctly.
        /// EDIT: Actually, no it doesn't, it throws a ClassCastException!
        ///       T is Boolean,
        ///       Whereas we're expecting a new type U <: Ordered[U]
        case gt:GreaterThan[T] => execute(gt.a) > execute(gt.b)
    }
}

Is this just a limitation of Scalas type inference, or am I missing something?

I also tried to achieve the same result using the Ordering [T] class, using context boundaries (this would be preferable)

case class GreaterThan[T : Ordering]( a:Expr[T], b:Expr[T] )

However, I cannot figure out how to access the typeclass instance inside the {} matching block without adding the method to GreaterThan itself (which somewhat strikes the point of using the class for this purpose.)

Effectively, what I'm trying to do is pass this Haskell to Scala

{-# LANGUAGE GADTs #-} 
data Expr a where
    StringLit   :: String  -> Expr String
    IntLit      :: Int     -> Expr Int
    Equals      :: (Eq a)  => (Expr a) -> (Expr a) -> Expr Bool
    GreaterThan :: (Ord a) => (Expr a) -> (Expr a) -> Expr Bool

runExpr :: Expr a -> a
runExpr (IntLit i)        = i
runExpr (StringLit s)     = s
runExpr (Equals a b)      = (runExpr a) == (runExpr b)
runExpr (GreaterThan a b) = (runExpr a) >  (runExpr b)
+4
1

, , , .

1.

:

case class GreaterThan[T <% Ordered[T]]( a:Expr[T], b:Expr[T]) extends Expr[Boolean]
case class GreaterThan[T : Ordering]( a:Expr[T], b:Expr[T]) extends Expr[Boolean]

:

case class GreaterThan[T]( a:Expr[T], b:Expr[T])(implicit evidence: T => Ordered[T]) extends Expr[Boolean]
case class GreaterThan[T]( a:Expr[T], b:Expr[T])(implicit ordering: Ordering[T]) extends Expr[Boolean]

case , Ordering. match > Ordered[T].

2. Erasure

:

case GreaterThan(a,b) => execute(a) > execute(b)

, Expr GreaterThan, - , GreaterThan. , , - . Ordered T => Ordered[T] GreaterThan . execute, T => Ordered[T] .

3.

, GreaterThan. :

case class GreaterThan[T]( a:Expr[T], b:Expr[T])(implicit val ordering: Ordering[T]) extends Expr[Boolean]

val Ordering .

match:

case gt: GreaterThan[_] => gt.ordering.gt(execute(gt.a), execute(gt.b))

, GreaterThan , , Ordering , .

Haskell , , , . Scala, .

, Haskell.

+3

Source: https://habr.com/ru/post/1538505/