There are number of great tutorials and posts out there covering the more straightforward of Lens's methods, e.g. Cleaner way to update nested structures; can anyone provide example uses for these three other methods? Thanks.
Unfortunately, Scalaz7 lens examples are a WIP. You need to ask this question of the Scalaz Google Group. Before you ask, try these examples here and watch Emmett's videos.
Using lenses with Scalaz 7
Emmett's videos on Lenses
Look at the source code again. What can you puzzle out from this?
def xmapbA[X, A >: A2 <: A1](b: Bijection[A, X]): LensFamily[X, X, B1, B2] =
xmapA(b to _)(b from _)
def xmapB[X1, X2](f: B1 => X1)(g: X2 => B2): LensFamily[A1, A2, X1, X2] =
lensFamily(a => run(a).xmap(f)(g))
def xmapbB[X, B >: B1 <: B2](b: Bijection[B, X]): LensFamily[A1, A2, X, X] =
xmapB(b to _)(b from _)
/** Modify the value viewed through the lens, returning a functor `X` full of results. */
def modf[X[+_]](f: B1 => X[B2], a: A1)(implicit XF: Functor[X]): X[A2] = {
val c = run(a)
XF.map(f(c.pos))(c put _)
}
Sorry for the minimal help. I can just point at whom to ask and what you need to know before you ask.
Related
I was recently reading Category Theory for Programmers and in one of the challenges, Bartosz proposed to write a function called memoize which takes a function as an argument and returns the same one with the difference that, the first time this new function is called, it stores the result of the argument and then returns this result each time it is called again.
def memoize[A, B](f: A => B): A => B = ???
The problem is, I can't think of any way to implement this function without resorting to mutability. Moreover, the implementations I have seen uses mutable data structures to accomplish the task.
My question is, is there a purely functional way of accomplishing this? Maybe without mutability or by using some functional trick?
Thanks for reading my question and for any future help. Have a nice day!
is there a purely functional way of accomplishing this?
No. Not in the narrowest sense of pure functions and using the given signature.
TLDR: Use mutable collections, it's okay!
Impurity of g
val g = memoize(f)
// state 1
g(a)
// state 2
What would you expect to happen for the call g(a)?
If g(a) memoizes the result, an (internal) state has to change, so the state is different after the call g(a) than before.
As this could be observed from the outside, the call to g has side effects, which makes your program impure.
From the Book you referenced, 2.5 Pure and Dirty Functions:
[...] functions that
always produce the same result given the same input and
have no side effects
are called pure functions.
Is this really a side effect?
Normally, at least in Scala, internal state changes are not considered side effects.
See the definition in the Scala Book
A pure function is a function that depends only on its declared inputs and its internal algorithm to produce its output. It does not read any other values from “the outside world” — the world outside of the function’s scope — and it does not modify any values in the outside world.
The following examples of lazy computations both change their internal states, but are normally still considered purely functional as they always yield the same result and have no side effects apart from internal state:
lazy val x = 1
// state 1: x is not computed
x
// state 2: x is 1
val ll = LazyList.continually(0)
// state 1: ll = LazyList(<not computed>)
ll(0)
// state 2: ll = LazyList(0, <not computed>)
In your case, the equivalent would be something using a private, mutable Map (as the implementations you may have found) like:
def memoize[A, B](f: A => B): A => B = {
val cache = mutable.Map.empty[A, B]
(a: A) => cache.getOrElseUpdate(a, f(a))
}
Note that the cache is not public.
So, for a pure function f and without looking at memory consumption, timings, reflection or other evil stuff, you won't be able to tell from the outside whether f was called twice or g cached the result of f.
In this sense, side effects are only things like printing output, writing to public variables, files etc.
Thus, this implementation is considered pure (at least in Scala).
Avoiding mutable collections
If you really want to avoid var and mutable collections, you need to change the signature of your memoize method.
This is, because if g cannot change internal state, it won't be able to memoize anything new after it was initialized.
An (inefficient but simple) example would be
def memoizeOneValue[A, B](f: A => B)(a: A): (B, A => B) = {
val b = f(a)
val g = (v: A) => if (v == a) b else f(v)
(b, g)
}
val (b1, g) = memoizeOneValue(f, a1)
val (b2, h) = memoizeOneValue(g, a2)
// ...
The result of f(a1) would be cached in g, but nothing else. Then, you could chain this and always get a new function.
If you are interested in a faster version of that, see #esse's answer, which does the same, but more efficient (using an immutable map, so O(log(n)) instead of the linked list of functions above, O(n)).
Let's try(Note: I have change the return type of memoize to store the cached data):
import scala.language.existentials
type M[A, B] = A => T forSome { type T <: (B, A => T) }
def memoize[A, B](f: A => B): M[A, B] = {
import scala.collection.immutable
def withCache(cache: immutable.Map[A, B]): M[A, B] = a => cache.get(a) match {
case Some(b) => (b, withCache(cache))
case None =>
val b = f(a)
(b, withCache(cache + (a -> b)))
}
withCache(immutable.Map.empty)
}
def f(i: Int): Int = { print(s"Invoke f($i)"); i }
val (i0, m0) = memoize(f)(1) // f only invoked at first time
val (i1, m1) = m0(1)
val (i2, m2) = m1(1)
Yes there is pure functional ways to implement polymorphic function memoization. The topic is surprisingly deep and even summons the Yoneda Lemma, which is likely what Bartosz had in mind with this exercise.
The blog post Memoization in Haskell gives a nice introduction by simplifying the problem a bit: instead of looking at arbitrary functions it restricts the problem to functions from the integers.
The following memoize function takes a function of type Int -> a and
returns a memoized version of the same function. The trick is to turn
a function into a value because, in Haskell, functions are not
memoized but values are. memoize converts a function f :: Int -> a
into an infinite list [a] whose nth element contains the value of f n.
Thus each element of the list is evaluated when it is first accessed
and cached automatically by the Haskell runtime thanks to lazy
evaluation.
memoize :: (Int -> a) -> (Int -> a)
memoize f = (map f [0 ..] !!)
Apparently the approach can be generalised to function of arbitrary domains. The trick is to come up with a way to use the type of the domain as an index into a lazy data structure used for "storing" previous values. And this is where the Yoneda Lemma comes in and my own understanding of the topic becomes flimsy.
Option is used for dealing with partiality in Scala, but we can also lift ordinary functions to the context of Options in order to handle errors. When implementing the function map2 I am curious on how to know when to use which functions. Consider the following implementation:
def map2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo map {bb =>
f(aa, bb)
aa is of type A, and bb is of type B which is then fed to F, giving us a C. However, if we do the following:
def map2_1[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo flatMap {bb =>
f(aa, bb)
aa is still of type A, and bb is still of type B, yet we will have to wrap the last call in Some(f(aa, bb)) in order to get an Option[C] instead of a regular C. Why is this? What does it mean to flatten on BO here?
Last and not least, one could do the simpler:
def map2_2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] = for {
as <- ao
bs <- bo
} yield(f(as,bs))
I know that for-comprehensions are syntactic sugar for ForEach'es, maps and flatmaps etc, but how do I, as a developer, know that the compiler will choose MAP with bs <- bo, and not flatMap?
I think I am on the verge of understanding the difference, yet nested flatmaps confuse me.
Taking the last question first, the developer knows what the compiler will do with for because the behaviour is defined and predictable: All <- turn into flatMap except the last one which will be either map or foreach depending on whether or not there is a yield.
The broader question seems to be about the difference between map and flatMap. The difference should be clear from the signatures e.g. for List these are the (simplified) signatures:
def map[B] (f: A => B) : List[B]
def flatMap[B](f: A => List[B]): List[B]
So map just replaces the values in a List with new values by applying f to each element of type A to generate a B.
flatMap generates a new list by concatenating the results of calling f on each element of the original List. It is equivalent to map followed by flatten (hence the name).
Intuitively, map is a one-for-one replacement whereas flatMap allows each element in the original List to generate 0 or more new elements.
What is the reason behind List.fill is being defined with two groups of parameters instead of one with n and elem parameters together
Current definition
def fill[A](n: Int)(elem: ⇒ A): CC[A]
Proposed definition
def fill[A](n: Int, elem: ⇒ A): CC[A]
Isn't it unnecessary boilerplate? Or is it designed to use the first part (List.fill(n)) as a curried function constructor?
You can write
List.fill(10){ val r = math.random; r * r }
but you cannot write
List.fill(10, r = math.random; r * r)
and
List.fill(10, {r = math.random; r * r})
looks somewhat awkward.
In this case, it's almost irrelevant, but note that the way how the arguments are grouped into argument lists can influence the type inference quite significantly, e.g.
def map[X, Y](a: F[X])(f: X => Y): F[Y]
works perfectly fine without any type annotations most of the time, whereas
def map[X, Y](a: F[X], f: X => Y): F[Y]
is quite painful to use. Take a careful look at such methods as ap, ap2 or map2 in this piece of code, for example. There is a good reason why the argument lists are the way they are, you would notice it immediately if they were defined differently.
I'm going to write this in Scala, but it's more of a functional programming question.
I have
def foo(x: A): Option[B]
and
def bar(x:B, y:B): C
What's the neatest way to do the following:
def compose(x:A, y:A): Option[C]
such that if either foo(x) of foo(y) are None, then compose(x,y) is None, otherwise compose(x,y) is bar(foo(x).get, foo(y).get). The best I could come up with is:
foo(a).flatMap( aRes => foo(b).map( bRes => bar(a,b)))
The following is syntactic sugar for your current solution:
def compose(x: A, y: A): Option[C] = for {
fx <- foo(x)
fy <- foo(y)
} yield bar(fx, fy)
Sometimes this approach is nicer than writing out flatMap and map, and sometimes it's not. You'll probably find that you pretty quickly develop strong preferences about this kind of thing. Either could be considered idiomatic Scala.
Since you've indicated that you're interested in the question more generally from the perspective of functional programming, however, it's worth noting that the solutions above are overkill in a sense. They take advantage of the fact that Option is monadic, but for this operation you don't actually need all of that power—the fact that Option has an applicative functor instance is enough. To summarize very informally, flatMap gives you sequencing that you don't need here, since the computation of fy doesn't depend on the computation of fx. Using the applicative functor for Option allows you to more clearly capture the fact that there's no dependency between the two computations.
The Scala standard library doesn't provide any kind of representation of applicative functors, but Scalaz does, and with Scalaz you could write your method like this (see the "appendix" of my answer here for some discussion of the syntax):
import scalaz._, Scalaz._
def compose(x: A, y: A): Option[C] = (foo(x) |#| foo(y))(bar)
This will produce the same result as the implementation above, but using a more appropriate abstraction.
How about:
for (x <- foo(a); y <- foo(b)) yield bar(x,y)
for instance:
type A = Int
type C = (A,A)
def foo(x: A): Option[A] = if (x > 0) Some(x) else None
def bar(x: A, y: A): C = x -> y
for (x <- foo(1); y <- foo(2)) yield bar(x,y)
// Option[C] = Some((1,2))
for (x <- foo(-1); y <- foo(2)) yield bar(x,y)
// Option[C] = None
Depending on your taste the very first could be written as:
for {
x <- foo(a)
y <- foo(b)
} yield bar(x,y)
I'm probably missing something that's right in the documentation, but I can't really make much sense of it - I've been teaching myself Scala mostly by trial and error.
Given a function f: A => C, what is the idiomatic way to perform the following conversions?
Either[A, B] -> Either[C, B]
Either[B, A] -> Either[B, C]
(If I have two such functions and want to convert both sides, can I do it all at once or should I apply the idiom twice sequentially?)
Option[A] -> Option[C]
(I have a feeling that this is supposed to use for (...) yield somehow; I'm probably just blanking on it, and will feel silly when I see an answer)
And what exactly is a "projection" of an Either, anyway?
You do either a:
either.left.map(f)
or a:
either.right.map(f)
You can also use a for-comprehension: for (x <- either.left) yield f(x)
Here's a more concrete example of doing a map on an Either[Boolean, Int]:
scala> val either: Either[Boolean, Int] = Right(5)
either: Either[Boolean, Int] = Right(5)
scala> val e2 = either.right.map(_ > 0)
either: Either[Boolean, Boolean] = Right(true)
scala> e2.left.map(!_)
either: Either[Boolean, Boolean] = Right(true)
EDIT:
How does it work? Say you have an Either[A, B]. Calling left or right creates a LeftProjection or a RightProjection object that is a wrapper that holds the Either[A, B] object.
For the left wrapper, a subsequent map with a function f: A => C is applied to transform the Either[A, B] to Either[C, B]. It does so by using pattern matching under the hood to check if Either is actually a Left. If it is, it creates a new Left[C, B]. If not, it just changes creates a new Right[C, B] with the same underlying value.
And vice versa for the right wrapper. Effectively, saying either.right.map(f) means - if the either (Either[A, B]) object holds a Right value, map it. Otherwise, leave it as is, but change the type B of the either object as if you've mapped it.
So technically, these projections are mere wrappers. Semantically, they are a way of saying that you are doing something that assumes that the value stored in the Either object is either Left or Right. If this assumption is wrong, the mapping does nothing, but the type parameters are changed accordingly.
Given f: A=>B and xOpt: Option[A], xOpt map f produces the Option[B] you need.
Given f: A=>B and xOrY: Either[A, C], xOrY.left.map(f) produces the Either you are looking for, mapping just the first component; similarly you can deal with RightProjection of Either.
If you have two functions, you can define mapping for both components, xOrY.fold(f, g).
val e1:Either[String, Long] = Right(1)
val e2:Either[Int,Boolean] = e1.left.map(_.size).right.map( _ >1 )
// e2: Either[Int,Boolean] = Right(false)