Home > Mobile >  PartialFunction to partially applied function
PartialFunction to partially applied function

Time:04-25

I'm trying to do the following:

val divide: PartialFunction[(Int, Int), Int] = {
    case (x, y) if (y != 0) => x / y
}

val divide42 = (y: Int) => divide((42, y))

However:

divide42.isDefinedAt(0)

cmd18.sc:1: value isDefinedAt is not a member of Int => Int
val res18 = divide42.isDefinedAt(0)
                     ^Compilation Failed

What is the right way to preserve PartialFunction functionality when going from PartialFunction to partially applied function?

CodePudding user response:

You can use compose to preserve the partial nature:

val divide: PartialFunction[(Int, Int), Int] = {
    case (x, y) if (y != 0) => x / y
}

val divide42: PartialFunction[Int, Int] = divide.compose {
  case y: Int => (42, y)  
}

divide42.isDefinedAt(0) // false

What you wrote doesn't work because it's actually syntactic sugar for the following:

val divide42 = new Function1[Int, Int] {
  def apply(y: Int) = divide((42, y))
}

The call to divide inside divide42 is an expression that evaluates to Int (or throw). There is no way to preserve the fact that divide is a partial function with this syntax.


Or explicitly write a new partial function like this but more verbose:

val divide: PartialFunction[(Int, Int), Int] = {
    case (x, y) if (y != 0) => x / y
}

val divide42: PartialFunction[Int, Int] = {
  case (y: Int) if divide.isDefinedAt((42, y)) => divide((42, y)) 
}

divide42.isDefinedAt(0) // false

CodePudding user response:

Help the compiler help you, define your types explicitly:

EDIT: I realized that simply changing the types results in the y != 0 part of the function not working as intended. compose addresses this as already mentioned in another answer (which is correct).

val divide: PartialFunction[(Int, Int), Int] = {
    case (x, y) if y != 0 => x / y
}


// OLD: val divide42: PartialFunction[Int, Int] = (y: Int) => divide((42, y))
// |- Returns true for `isDefinedAt(0)` which is WRONG!!
// |- If someone could explain why this happens (???), please comment :)

val divide42: PartialFunction[Int, Int] = (y: Int) => divide.compose {
    case y: Int => (42, y)
}

divide42.isDefinedAt(0) // False

When you define it as you have, the compiler changes the type of divide42 to Int => Int as opposed to PartialFunction[Int, Int]:

// Implicit type, `Int => Int`
val divide42 = (y: Int) => divide((42, y))

// `isDefinedAt` is not defined for `Int => Int`
divide42.isDefinedAt(0) // !! Error !!

CodePudding user response:

The following seem right to me:

val divide: PartialFunction[(Int, Int), Int] = {
    case (x, y) if (y != 0) => x / y
}

val divide42: PartialFunction[Int, Int] = {
    case x if (x != 0) => divide(42, x)
}

divide42.isDefinedAt(0) // false

divide42(6) // 7

This both follows the correct definition pattern for PartialFunction and suits the definition of a partially applied function

  • Related