Skip to content

Instantly share code, notes, and snippets.

@tonymorris
Created May 31, 2013 11:35

Revisions

  1. tonymorris created this gist May 31, 2013.
    44 changes: 44 additions & 0 deletions RefactoringPuzzle.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    object RefactorPuzzle {
    case class IntRdr[+A](read: Int => A) {
    def map[B](f: A => B): IntRdr[B] =
    IntRdr(f compose read)

    def flatMap[B](f: A => IntRdr[B]): IntRdr[B] =
    IntRdr(n => f(read(n)).read(n))
    }

    object IntRdr {
    def apply[A](a: A): IntRdr[A] =
    IntRdr(_ => a)
    }

    // Return all the Some values, or None if not all are Some.
    def runOptions[A](x: List[Option[A]]): Option[List[A]] =
    x.foldRight[Option[List[A]]](Option(Nil))((a, b) => a.flatMap(aa => b.map(aa :: _)))

    // Apply an Int to a list of int readers and return the list of return values.
    def runIntRdrs[A](x: List[IntRdr[A]]): IntRdr[List[A]] =
    x.foldRight[IntRdr[List[A]]](IntRdr(Nil))((a, b) => a.flatMap(aa => b.map(aa :: _)))

    /*
    ========================
    THE REFACTORING PUZZLE
    ========================
    The two functions `runOptions` and `runIntRdrs` share a lot of duplicated code.
    This is demonstrated below.
    How to refactor this code to remove the code duplication?
    */

    //------- ------------- ------- -----------
    //def runOptions[A](x: List[Option[A]]): Option[List[A]] =
    //def runIntRdrs[A](x: List[IntRdr[A]]): IntRdr[List[A]] =

    // ------------ ----------- -------------------------------------------------
    // x.foldRight[Option[List[A]]](Option(Nil))((a, b) => a.flatMap(aa => b.map(aa :: _)))
    // x.foldRight[IntRdr[List[A]]](IntRdr(Nil))((a, b) => a.flatMap(aa => b.map(aa :: _)))

    }