Assignment 7
[Scala.git] / Assignment_07 / src / main / scala / Main.scala
diff --git a/Assignment_07/src/main/scala/Main.scala b/Assignment_07/src/main/scala/Main.scala
new file mode 100644 (file)
index 0000000..ebd6d30
--- /dev/null
@@ -0,0 +1,95 @@
+object Main {
+
+  // Question 1.
+  trait Stack[+A] {
+    def push[B >: A](elem: B): Stack[B]
+    def top: A
+    def pop: Stack[A]
+  }
+
+  case class EmptyStack[A]() extends Stack[A] {
+    def push[B >: A](elem: B): Stack[B] = ElemStack(elem, this)
+    def top: A = throw new Exception
+    def pop: Stack[A] = throw new Exception
+  }
+
+  case class ElemStack[A](top: A, rest: Stack[A]) extends Stack[A] {
+    def push[B >: A](elem: B): Stack[B] = ElemStack(elem, this)
+    def pop: Stack[A] = rest
+    override def toString = s"${top.toString()},${rest.toString()}"
+  }
+
+  def question1 = {
+    println("Question 1")
+    // Construction, pop and toString.
+    val a = EmptyStack().push("hello").push("world").push("it's fun").pop
+    println(s"a: ${a}")
+    assert(a.toString() == "world,hello,EmptyStack()")
+
+    // Getting top.
+    val b = EmptyStack().push(1).push(3)
+    println(s"b.top: ${b.top}")
+    assert(b.top == 3)
+
+    // Variance checks.
+    class Foo
+    class Bar extends Foo
+    val c: Stack[Bar] = EmptyStack().push(new Bar()).push(new Bar())
+    assert(c.top.isInstanceOf[Bar])
+    assert(c.top.isInstanceOf[Foo])
+
+    // Variance check 2.
+    val d: Stack[Foo] = EmptyStack().push(new Bar()).push(new Bar())
+    assert(d.top.isInstanceOf[Foo])
+  }
+
+  // Question 2.
+  abstract sealed class Temperature {
+    val temp: Double
+  }
+
+  case class Celsius(v: Double) extends Temperature {
+    val temp = v
+    override def toString = s"$v° C"
+  }
+
+  case class Kelvin(v: Double) extends Temperature {
+    val temp = v
+    override def toString = s"$v° K"
+  }
+
+  object Temperature {
+    implicit def toCelsius(temp: Kelvin): Celsius = new Celsius(temp.v + 273.15)
+    implicit def toCelsius(temp: Int): Celsius = new Celsius(temp)
+    implicit def toKelvin(temp: Celsius): Kelvin = new Kelvin(temp.v - 273.15)
+    implicit def toKelvin(temp: Int): Kelvin = new Kelvin(temp)
+  }
+
+  def question2 = {
+    println("Question 2")
+    val a: Celsius = 30
+    val b: Kelvin = 30
+    val c: Kelvin = Celsius(10)
+    val d: Celsius = c
+    val e: Temperature = d
+    println(a)
+    println(b)
+    println(e)
+  }
+
+  // Question 3.
+  def addStream(s1: Stream[Int], s2: Stream[Int]): Stream[Int] =
+    (s1.head + s2.head) #:: addStream(s1.tail, s2.tail)
+
+  lazy val fib: Stream[Int] = 0 #:: 1 #:: addStream(fib, fib.tail)
+
+  def question3 = {
+    println(fib.take(30).toList)
+  }
+
+  def main(args: Array[String]): Unit = {
+    question1
+    question2
+    question3
+  }
+}