Replacing case class inheritance with extractors preserving exhaustiveness checks in Scala

后端 未结 3 1299
说谎
说谎 2021-01-04 23:39

I have a simple class hierarchy that represents a graph-like structure with several distinct types of vertexes implemented using case classes:

sealed trait N         


        
相关标签:
3条回答
  • 2021-01-04 23:46

    extractors give you the possibility to use it in pattern matching like case classes in scala, but they don´t have other standard implementations you get when using the case modifier. But hust these extra implementation(especially the implementation of equals) is what makes case class inheritance dangerous and so it got deprecated.

    However sealed classes are an orthogonal feature and you can use them whether or not you have a case class or an extractor. By using extractors you don´t get standard implementations on the fly but thus you can have inheritance of extractors - they are simply normal classes with an unapply and/or unapplySeq method.

    What You´ve done in your example is called pattern-matching on types. If you only want to do this, you don´t need case classes neither extractors. You can do it with every class you want. So you can simply remove the case modifier.

    So to conclude: exhaustiveness of pattern is achieved by sealed class hirachies. Pattern matching is achieved by extractors and case classes of what the latter is just an extractor with appealing standard implementations of frequently used functions. I hope this helped.

    0 讨论(0)
  • 2021-01-05 00:03

    In general, this can't be done.

    Sealed classes are a special case (no pun intended) because scalac knows at compile time how many matches are possible.

    But since extractors allow you to run arbitrary code and because of the damnable halting problem, there's no way for the compiler to guarantee in every case that you'll check every case. Consider:

    def test(foo: Int) {
      foo match {
        case IsMultipleOf8(n) => printf("%d was odd\n", n)
      }
    }
    

    This is not exhaustive because it doesn't handle numbers that aren't multiples of 8, but the compiler cannot deduce (without running your extractor on all Int's) that only some values of type Int are multiples of 8.

    0 讨论(0)
  • 2021-01-05 00:08

    The citation from scala-lang.org:

    If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchErrorbeing raised at run-time.

    0 讨论(0)
提交回复
热议问题