/* * Copyright 2014–2018 SlamData Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package matryoshka.instances.fixedpoint import slamdata.Predef._ import matryoshka._ import matryoshka.implicits._ import matryoshka.scalacheck.arbitrary._ import org.specs2.ScalaCheck import org.specs2.mutable._ import org.specs2.scalaz.{ScalazMatchers} import scalaz._, Scalaz._ class StreamSpec extends Specification with ScalaCheck with ScalazMatchers { /** Infinite sequence of Fibonacci numbers (at least until they overflow * int32) */ val fib = (1, 0).ana[Stream[Int]](binarySequence(_ + _)) /** Generates an infinite stream of the carrier value. */ def constantly[A]: Coalgebra[(A, ?), A] = i => (i, i) "fib" should { "begin with 1" in { fib.head must equal(1) } "lazily generate the correct sequence" in { 5.anaM[Nat](Nat.fromInt) ∘ (fib.drop(_).head) must equal(8.some) } "have a proper prefix" in { 5.anaM[Nat](Nat.fromInt) ∘ (fib.take[List[Int]](_)) must equal(List(1, 1, 2, 3, 5).some) } "get a subsequence" in { (10.anaM[Nat](Nat.fromInt) ⊛ 5.anaM[Nat](Nat.fromInt))((d, t) => fib.drop(d).take[List[Int]](t)) must equal(List(89, 144, 233, 377, 610).some) } } "constantly" should { "begin with the given value" >> prop { (i: Int) => i.ana[Stream[Int]](constantly).head must_== i } // FIXME: These two blow up the stack with much larger inputs "have the given value at an arbitrary point" >> prop { (i: Int, d: Int) => 350.anaM[Nat](Nat.fromInt) ∘ (i.ana[Stream[Int]](constantly).drop(_).head) must equal(i.some) } "have subsequence of the given value" >> prop { (n: Nat, i: Int, t: Int) => i.ana[Stream[Int]](constantly).take[List[Int]](n) must equal(List.fill[List[Int]](n)(i)) } } }