Chaining PartialFunctions with andThen in Scala

前端 未结 3 1282
暗喜
暗喜 2020-12-20 12:56

Let us reuse examples from Daily scala :

type PF = PartialFunction[Int,Int]

val pf1 : PF = {case 1 => 2}                      

val pf2 : PF = {case 2 =&         


        
相关标签:
3条回答
  • 2020-12-20 13:31

    You need the equivalent of flatMap for PartialFunctions.

    implicit class CollectPartial[A, B](f: PartialFunction[A, B]) {
        def collect[C](g: PartialFunction[B, C]) = Function.unlift { a: A =>
            f.lift(a).flatMap(g.lift)
        }
    }
    

    Use it like

    val a: PartialFunction[String, Int] = ...
    val b: PartialFunction[Int, Char] = ...
    val c: PartialFunction[String, Char] = a collect b
    

    This works as expected even with side-effects.

    0 讨论(0)
  • 2020-12-20 13:39

    Why not simply :

    def compose[A,B,C](f: PartialFunction[A, B], g: PartialFunction[B, C]) : PartialFunction[A, C] =
    Function.unlift(f.andThen(g.lift))
    
    0 讨论(0)
  • 2020-12-20 13:45

    If you look at andThen:

    def andThen[C](k: (B) => C): PartialFunction[A, C]
    

    This composes the receiver with a function and not a partial function. That is, k is expected to be fully defined, it doesn't have isDefinedAt. Therefore, the resulting partial function does not need to alter the behaviour of isDefinedAt, it will still just has to consult the first partial function.

    You could write your own extension that composes two partial functions:

    implicit class ComposePartial[A, B](pf: PartialFunction[A, B]) {
      def collect[C](that: PartialFunction[B, C]): PartialFunction[A, C] =
        new PartialFunction[A, C] {
          def apply(a: A): C = that(pf(a))
          def isDefinedAt(a: A) = pf.isDefinedAt(a) && {
            val b = pf(a)
            that.isDefinedAt(b)
          }
        }
    }
    
    pf1 collect pf2 isDefinedAt(1)  // true
    pf1 collect pf3 isDefinedAt(1)  // false
    

    The problem is that you have to invoke pf(a), so given that Scala doesn't enforce purity, you may end up executing side effects unwantedly.

    0 讨论(0)
提交回复
热议问题