Defining implicit view-bounds on Scala traits

后端 未结 3 1057
长情又很酷
长情又很酷 2021-02-13 10:28

I\'m doing an exercise to implement a functional binary-search-tree in Scala, following a similar pattern that I\'ve seen used in Haskell. I have a structure that looks somethin

3条回答
  •  醉梦人生
    2021-02-13 11:02

    The problem is that view bounds as well as context bounds are just syntactic sugar for specific types of implicit parameters. When applied to a type parameter of a generic class (as opposed to when applied to a generic method), these implicits are added to the constructor of the class. Because traits have no constructor (or rather, only have a single parameterless constructor), there is nowhere to pass these implicit parameters and thus context bounds and view bounds are illegal on generic traits. The simplest solution would be to turn TreeNode into an abstract class.:

    abstract class TreeNode[A <% Ordered[A]]
    

    Note that as advised by Ben James, using a context bound with an Ordering is usually better than a view bound with an Ordered (it is more general). However the problem is still the same: won't work on a trait.

    If turning TreeNode into a class is not practical (say you need to mix it at various places in the type hierarchy), you can define an abstract method in TreeNode that will provide the implicit value (of type Ordered[A]) and have all the classes that extend it define it. This unfortunately more verbose and explicit, but you can't do much better in this case:

    trait TreeNode[A] {
      implicit protected def toOrdered: A => Ordered[A]
    }
    
    case class Branch[A<%Ordered[A]](value: A, left: TreeNode[A], right: TreeNode[A]) extends TreeNode[A] { 
       protected def toOrdered = implicitly[A => Ordered[A]]
    }
    
    case class Leaf[A<%Ordered[A]]() extends TreeNode[A] { 
        protected def toOrdered = implicitly[A => Ordered[A]]
    }
    

    Note that for a more concise definition, you could equivalently define Leaf like this:

    case class Leaf[A](implicit protected val toOrdered: A => Ordered[A]) extends TreeNode[A]
    

提交回复
热议问题