Let's say we are looking for a method which, given a function of type A=>B, would return a function of type F[A]=>F[B] where F is a container of some sort, such as Option, Seq, Try, etc. In particular, we will require that F be a functor because it is obviously going to require the map method. In other words we need a body for the following signature:
def lift[A,B](f: A => B): F[A] => F[B] = ???
def lift[A,B](f: A => B): F[A] => F[B] = _ map f
def liftOption[A,B](f: A => B): Option[A] => Option[B] = _ map f
def liftSeq[A,B](f: A => B): Seq[A] => Seq[B] = _ map f
Here's another example. I've been working on a type of number that is lazily evaluated when a function is applied to it. This will form part of a fuzzy number suite that I'm developing. I could perhaps use Real from Spire but for now I want to keep it simple without bringing in any external libraries. To begin with, my lazy number class is defined thus:
where Valuable defines the (abstract) get method, construct is implemented by sub-classes (we could call it unit if we liked). So, the value of a lazy number is f(x) and applying a function g to this lazy number consists of composing function g with f and leaving x as is. What about flatMap? We'd like to be able to construct for-comprehensions with our lazy numbers, wouldn't we? So, we need a body for the following signature:abstract class LazyNumber[X : Fractional](x: X, f: X=>X) extends Valuable[X] with Fractional[LazyNumber[X]] {
def get = f(x)def construct(x: X, f: X=>X): LazyNumber[X]def map(g: X=>X): LazyNumber[X] = construct(x,g.compose(f))...}
def flatMap(g: X=>LazyNumber[X]): LazyNumber[X] = ???
def flatMap(g: X=>LazyNumber[X]): LazyNumber[X] = g(f(x))
Could anything possibly be more obvious, simple or elegant?
* We could easily get into a debate here: receiver is really an artifact of object-oriented programming -- from a functional programming point of view, the two parameters to the map function (the pre-parameter and the post-parameter) are just parameters.
No comments:
Post a Comment