Partial functions in Scala

Deepak Kumar
3 min readOct 16, 2020

--

According to mathematical definition a function which is defined for some range of a domain and not defined for some other range of the same domain is called a partial function.

A simple example would be division of a number by an integer ‘x’.

f(x) = N/x

Here you know that division by ‘0’ is not possible therefore the domain of ‘f’ does not include the integer ‘0’.

Similarly any function that applies only to a subset of a domain can be represented as a partial function. Scala standard library provides us with a trait PartialFunction which is of the following signature. This trait allows us to define partial functions which takes a single parameter.

trait PartialFunction[-A, +B] extends (A) => B

The signature implies it is a function that takes a single parameter of contravarient nature (ie, a subtype of A be given as input) and returns something of covarient nature (ie, a super type of B could be returned as output)

From the Scala standard library documentation

A partial function of type PartialFunction[A, B] is a unary function where the domain does not necessarily include all values of type A. The function isDefinedAt allows to test dynamically if a value is in the domain of the function.

Lets take an example of a set of weekdays, we have seven weekdays but how do you represent them? Well you could represent them as a subset of strings containing only seven strings. Then if we have a function that accepts a string and returns the day of the week as a an integer is going to be a partial function by definition.

def getDay(day: String): Int = day match {
case "sunday" => 1
case "monday" => 2
case "tuesday" => 3
case "wednesday" => 4
case "thursday" => 5
case "friday" => 6
case "saturday" => 7
}

getDay("monday") // res10: Int = 2
getDay("someday") // scala.MatchError: ...

The above method does what we wanted, but Scala provides a verbose way by which we can represent it as a partial function.

def getDay: PartialFunction[String, Int] = {
case "sunday" => 1
case "monday" => 2
case "tuesday" => 3
case "wednesday" => 4
case "thursday" => 5
case "friday" => 6
case "saturday" => 7
}

getDay("monday")
getDay("someday") // scala.MatchError: ...

Another representation would be using ADT we could create a set of all weekdays. If the domain is defined and all the members are handled then it becomes a total function.

sealed trait Weekday
case object Sunday extends Weekday
case object Monday extends Weekday
case object Tuesday extends Weekday
case object Wednesday extends Weekday
case object Thursday extends Weekday
case object Friday extends Weekday
case object Saturday extends Weekday

def getDay: PartialFunction[Weekday, Int] = {
case Sunday => 1
case Monday => 2
case Tuesday => 3
case Wednesday => 4
case Thursday => 5
case Friday => 6
case Saturday => 7
}
getDay(Sunday)
getDay(Someday) // does not compile

But the problem here is we have converted this to a total function, so it is theoretically incorrect to define it using trait PartialFunction. This could be better written as a total function as follows.

val getDay: Weekday => Int = (weekday) => weekday match {
case Sunday => 1
case Monday => 2
case Tuesday => 3
case Wednesday => 4
case Thursday => 5
case Friday => 6
case Saturday => 7
}
getDay(Sunday)

As you can see in the above approach the the codes doesn’t even compile, the type check fails which is a great thing when it comes to correctness of the program.

But in general partial functions are very useful in day to day programming because we don’t always prefer creating a domain and converting that to a total function. We mostly prefer to work with basic types or derived types instead of defining ADT for the whole domain, but if the overhead of defining an ADT makes sense then it should be done.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Deepak Kumar
Deepak Kumar

No responses yet

Write a response