Assignment 7
[Scala.git] / Assignment_07 / src / main / scala / Main.scala
1 object Main {
2
3 // Question 1.
4 trait Stack[+A] {
5 def push[B >: A](elem: B): Stack[B]
6 def top: A
7 def pop: Stack[A]
8 }
9
10 case class EmptyStack[A]() extends Stack[A] {
11 def push[B >: A](elem: B): Stack[B] = ElemStack(elem, this)
12 def top: A = throw new Exception
13 def pop: Stack[A] = throw new Exception
14 }
15
16 case class ElemStack[A](top: A, rest: Stack[A]) extends Stack[A] {
17 def push[B >: A](elem: B): Stack[B] = ElemStack(elem, this)
18 def pop: Stack[A] = rest
19 override def toString = s"${top.toString()},${rest.toString()}"
20 }
21
22 def question1 = {
23 println("Question 1")
24 // Construction, pop and toString.
25 val a = EmptyStack().push("hello").push("world").push("it's fun").pop
26 println(s"a: ${a}")
27 assert(a.toString() == "world,hello,EmptyStack()")
28
29 // Getting top.
30 val b = EmptyStack().push(1).push(3)
31 println(s"b.top: ${b.top}")
32 assert(b.top == 3)
33
34 // Variance checks.
35 class Foo
36 class Bar extends Foo
37 val c: Stack[Bar] = EmptyStack().push(new Bar()).push(new Bar())
38 assert(c.top.isInstanceOf[Bar])
39 assert(c.top.isInstanceOf[Foo])
40
41 // Variance check 2.
42 val d: Stack[Foo] = EmptyStack().push(new Bar()).push(new Bar())
43 assert(d.top.isInstanceOf[Foo])
44 }
45
46 // Question 2.
47 abstract sealed class Temperature {
48 val temp: Double
49 }
50
51 case class Celsius(v: Double) extends Temperature {
52 val temp = v
53 override def toString = s"$v° C"
54 }
55
56 case class Kelvin(v: Double) extends Temperature {
57 val temp = v
58 override def toString = s"$v° K"
59 }
60
61 object Temperature {
62 implicit def toCelsius(temp: Kelvin): Celsius = new Celsius(temp.v + 273.15)
63 implicit def toCelsius(temp: Int): Celsius = new Celsius(temp)
64 implicit def toKelvin(temp: Celsius): Kelvin = new Kelvin(temp.v - 273.15)
65 implicit def toKelvin(temp: Int): Kelvin = new Kelvin(temp)
66 }
67
68 def question2 = {
69 println("Question 2")
70 val a: Celsius = 30
71 val b: Kelvin = 30
72 val c: Kelvin = Celsius(10)
73 val d: Celsius = c
74 val e: Temperature = d
75 println(a)
76 println(b)
77 println(e)
78 }
79
80 // Question 3.
81 def addStream(s1: Stream[Int], s2: Stream[Int]): Stream[Int] =
82 (s1.head + s2.head) #:: addStream(s1.tail, s2.tail)
83
84 lazy val fib: Stream[Int] = 0 #:: 1 #:: addStream(fib, fib.tail)
85
86 def question3 = {
87 println(fib.take(30).toList)
88 }
89
90 def main(args: Array[String]): Unit = {
91 question1
92 question2
93 question3
94 }
95 }