Pattern matching and infinite streams

后端 未结 2 1688
深忆病人
深忆病人 2021-02-07 03:52

So, I\'m working to teach myself Scala, and one of the things I\'ve been playing with is the Stream class. I tried to use a naïve translation of the classic Haskell

2条回答
  •  深忆病人
    2021-02-07 04:08

    Note that you can do what you want by defining a better pattern matcher for Stream:

    Here's a bit I just pulled together in a Scala Worksheet:

    object HammingTest {
      // A convenience object for stream pattern matching
      object #:: {
        class TailWrapper[+A](s: Stream[A]) {
          def unwrap = s.tail
        }
        object TailWrapper {
          implicit def unwrap[A](wrapped: TailWrapper[A]) = wrapped.unwrap
        }
        def unapply[A](s: Stream[A]): Option[(A, TailWrapper[A])] = {
          if (s.isEmpty) None
          else {
            Some(s.head, new TailWrapper(s))
          }
        }
      }
    
      def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
        (a, b) match {
          case (x #:: xs, y #:: ys) =>
            if (x < y) x #:: merge(xs, b)
            else if (y < x) y #:: merge(a, ys)
            else x #:: merge(xs, ys)
        }                                             //> merge: (a: Stream[BigInt], b: Stream[BigInt])Stream[BigInt]
    
      lazy val numbers: Stream[BigInt] =
        1 #:: merge(numbers map { _ * 2 }, merge(numbers map { _ * 3 }, numbers map { _ * 5 }))
                                                      //> numbers  : Stream[BigInt] = 
      numbers.take(10).toList                         //> res0: List[BigInt] = List(1, 2, 3, 4, 5, 6, 8, 9, 10, 12)
    }
    

    Now you just need to make sure that Scala finds your object #:: instead of the one in Stream.class whenever it's doing pattern matching. To facilitate that, it might be best to use a different name like #>: or ##:: and then just remember to always use that name when pattern matching.

    If you ever need to match the empty stream, use case Stream.Empty. Using case Stream() will attempt to evaluate your entire stream there in the pattern match, which will lead to sadness.

提交回复
热议问题