forked from wjlow/intro-to-scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TryExercises.scala
150 lines (133 loc) · 4.08 KB
/
TryExercises.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package fundamentals.level03
import scala.util.{Try, Success, Failure}
/**
* These exercises use the `Try` ADT for working with code that throw exceptions (e.g. Java AWS library).
*
* `Try` is very similar to `Either`. Instead of having a `Right` and a `Left`, it has a `Success` and a `Failure`.
* A value of `Try[A]` is one of `Success(a: A)` or `Failure(exception: Exception)`.
*
* You can think of `Try[A]` ~ `Either[Throwable, A]`
*
* `Try` comes with a constructor that can be used to wrap any expression that may throw an exception. We will see more of this later.
*/
object TryExercises {
/**
* What's wrong with this function?
*/
def parseInt(str: String): Int = str.toInt
/**
* What's a safe return type?
*
* Expressions that throw exceptions can be surrounded by `Try`:
*
* ```
* Try(mayThrowException())
* ```
*
* You can pattern match of `Try` using its two constructors `Success` and `Failure`:
*
* ```
* Try(mayThrowException()) match {
* case Success(a) => // do something with `a`
* case Failure(exception) => // do something with `exception`
* }
* ```
*
* scala> parseIntSafe("1")
* = Success(1)
*
* scala> parseIntSafe("abc")
* = Failure(java.lang.NumberFormatException: For input string: "abc")
*
* Hint: Use `Try` and `parseInt`
*/
def parseIntSafe(str: String): Try[Int] = ???
/**
* scala> parseBooleanSafe("true")
* = Success(true)
*
* scala> parseBooleanSafe("abc")
* = Failure(java.lang.IllegalArgumentException: For input string: "abc")
*
* Hint: Use .toBoolean to convert a String to a Boolean
**/
def parseBooleanSafe(str: String): Try[Boolean] = ???
/**
* scala> increment("10")
* = Success(11)
*
* scala> increment("NaN")
* = Failure(java.lang.NumberFormatException: For input string: "NaN")
*
* Hint: Solve it without using pattern matching
*/
def increment(str: String): Try[Int] = ???
/**
* Remember that `Try[A]` ~ `Either[Throwable, A]`
*
* Let's write a function that converts a `Try[A]` to `Either[TryError, A]`, where `TryError` is our custom error type.
*
* Hint: You can convert a `Throwable` to a `String` using `.getMessage`
*/
case class TryError(msg: String)
def tryToEither[A](tryA: Try[A]): Either[TryError, A] =
tryA match {
case Success(a) => ???
case Failure(throwable) => ???
}
/**
* Write a function that converts a `Try[A]` to `Option[A]`.
*
* scala> tryToOption(parseIntSafe("1"))
* = Some(1)
* scala> tryToOption(parseIntSafe("abc"))
* = None
*/
def tryToOption[A](tryA: Try[A]): Option[A] =
tryA match {
case Success(a) => ???
case Failure(throwable) => ???
}
/**
* Create an Employee data type with three parameters:
* 1. name: String
* 2. age: Int
* 3. hasDirectReports: Boolean
*/
trait Employee
/**
* Now remove `import TryTestTypes._` from `TryExercisesTest.scala`
*/
/**
* Create a CSV parser to safely create an Employee
*
* scala> mkEmployee("Bob,22,true")
* = Right(Employee("Bob", 22, true))
*
* scala> mkEmployee("Bob,abc,true")
* = Left(TryError(For input string: "abc"))
*
* scala> mkEmployee("Bob,22,abc")
* = Left(TryError(For input string: "abc"))
*
* scala> mkEmployee("Bob,22")
* = Left(TryError(CSV has wrong number of fields. Expected 3.))
*
* Hint: Use `parseIntSafe`, `parseBooleanSafe`, for-comprehension, `tryToEither`
*/
def mkEmployee(csv: String): Either[TryError, Employee] =
csv.split(",") match {
case Array(nameStr, ageStr, hasDirectReportsStr) => ???
case _ => ???
}
/**
* @param filename Path to file containing employees data, e.g. "src/main/resources/employees.csv"
* @return List of Employees and/or errors if any
*
* Hint: Use `mkEmployee`
*/
def fileToEmployees(filename: String): List[Either[TryError, Employee]] = {
val lines: List[String] = io.Source.fromFile(filename).getLines().toList
???
}
}