Functional Programming in Scala defines Applicative#traverse as:
def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]]
as.foldRight(unit(List[B]()))((a, fbs) => map2(f(a), fbs)(_ :: _))
However, I implemented this function as:
def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]] =
as.foldRight(unit(List[B]()))((elem, acc) => map2(acc, f(elem))(_ :+ _))
With unit and map2 defined as:
def map2[A,B,C](fa: F[A], fb: F[B])(f: (A,B) => C): F[C]
def unit[A](a: => A): F[A]
As I understand my implementation, the map2(acc, f(elem))(_ :+ _)) will behave as so:
for each (element, accumulator), call map2(acc, f(elem)(_ :+ _))
to append the result of f(elem) (type F[B]) to the accumulator (type F[List[B]])
For my implementation, then, in the (f: (A,B) => C) part of traverse's map2 calls, List[B] appends B to itself.
map2 accepts arguments F[A] and F[B], but the function argument f operates on the A and B types. In the FP in Scala solution, B gets added to List[B] via the :: operator.
Is that right?
You are correct in your understanding of what is going on. Note, however, that your implementation will produce a list in the reverse order of what is expected, so if you used the identity monad as F, you'd get back a reversed list, instead of the same list.
Related
I am confused about what this means.
I understand currying but I can't seem to read the code altogether.
def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
Let's dive into this method signature:
foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
foldLeft is a method with 3 parameters
A and B are type parameters
xs is 1st parameter of the method, of type List[A]
e is 2nd parameter, of type B
f is 3rd parameter, of type (B, A) => B
the type (B, A) => B represents a function taking two parameters of type B and A respectively, and returning a B
finally, B is the return type of the method
Just a couple of advices.
By the way, there is no currying in
def foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
Currying would be if you had f: B => A => B or def foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): B or def foldLeft[A, B]: List[A] => B => ((B, A) => B) => B etc. Now foldLeft is just a higher-order function (method), i.e. a function accepting another function (f).
You can read wiki article about foldRight/foldLeft:
https://en.wikipedia.org/wiki/Fold_(higher-order_function)
Especially look at the pictures how we deconstruct a list and starting from what end we perform our calculations:
You can think of foldRight/foldLeft as a just short way to define a recursion (instead of pattern matching a list and making recursive calls).
Let's consider an example. Let's have some recursion. For example let's have a wrapper class
case class Value[A](value: A)
And let's transform a list of Value[A] into a value wrapping a list of A i.e. List[Value[A]] into Value[List[A]]. For example we'd like to transform List(Value(1), Value(2), Value(3)) into Value(List(1, 2, 3)) (I actually needed such function recently). Surely, we could do this with .map but let's pretend that we don't know map (it shouldn't be surprising that we can do mapping because map can be expressed via foldRight/foldLeft).
We can do this recursively in two ways (at least). Either simple recursion
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = values match {
case Nil => Value(Nil)
case v :: vs => Value(v.value :: valuesToValue(vs).value)
}
or tail recursion with a helper function and accumulator
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
#tailrec
def loop(values: List[Value[A]], acc: Value[List[A]]): Value[List[A]] = values match {
case Nil => Value(acc.value.reverse)
case v :: vs => loop(vs, Value(v.value :: acc.value))
}
loop(values, Value(Nil))
}
Very simple. Just wrapping-unwrapping.
Both recursive implementations of valuesToValue can be (automatically) re-written with foldRight/foldLeft.
The former recursion can be re-written with foldRight. The latter recursion (tail one) can be re-written with foldLeft.
Let's re-write the 1st recursion with foldRight. The value from branch case Nil => ... becomes the 1st argument of foldRight. The value from branch case v :: vs => ... becomes the 2nd argument of foldRight if we replace the result of recursive call valuesToValue(vs) with a new variable res, so in the 2nd argument of foldRight we'll have a function of v: Value[A] and res: Value[List[A]]
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] =
values.foldRight( Value(Nil: List[A]) ){
(v, res) => Value(v.value :: res.value)
}
Let's re-write the 2nd recursion (tail one) with foldLeft.
First of all, let's recall that because of currying we can understand the helper loop as a single-parameter function into Value[List[A]] => Value[List[A]]
def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] = values match {
case Nil => acc => Value(acc.value.reverse)
case v :: vs => acc => loop(vs)(Value(v.value :: acc.value))
}
Now the value from branch case Nil => ... becomes the 1st argument of foldLeft. The value from branch case v :: vs => ... becomes the 2nd argument of foldLeft if we replace the result of recursive call loop(vs)(_) with a new variable res (a function)
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] =
values.foldRight[Value[List[A]] => Value[List[A]]](
acc => Value(acc.value.reverse)
)(
(v, res) => acc => res(Value(v.value :: acc.value))
)
loop(values)(Value(Nil))
}
So, roughly speaking, values from branches case Nil => ... and case v :: vs => ... become arguments of foldRight/foldLeft depending on whether we calculate with simple recursion or tail recursion with accumulator.
I am having problems understanding this code from the Book FP in Scala. Here is the code:
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
def op(f: A => A, g: A => A) = f compose g
val zero = (a: A) => a
}
def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B =
as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))
// The function type `(A, B) => B`, when curried, is `A => (B => B)`.
// And of course, `B => B` is a monoid for any `B` (via function composition).
def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B): B =
foldMap(as, endoMonoid[B])(f.curried)(z)
foldMap is expecting a function f: A => B.
In foldRight, when f is curried you have A => (B => B), so I suppose f.curried is working because it is the same as (A => B => B), so foldRight is passing in to foldMap what it expect (a function with type A => B), then, what happends next is that foldMap is called and its returning a function B => B, and that's when z comes into play in (f.curried)(z) you call the function B => B with the argument z to get the final B.
Am I right? it is a litle complicated to reason about this code for me.
NOTE: Here is a scalafiddle if you want to play with it.
Well, you seem to be mostly comprehensive to me. Nevertheless, I would clarify some points:
I'd rather say "so I suppose f.curried is working because A => (B => B) is the same as (A => B => B)" (it is ambiguous here and you're talking about f.curried result type basically, not with z)
I'd rather put a point instead of a comma here: "foldMap is expecting a function f: A => B . In foldRight, ... " and pretty much every where else. Shorter phrases, clearer explanation.
what could be an error, (and what is confusing to you?) is that (f.curried)(z) doesn't work on its own and is not called after foldMap(as, endoMonoid[B]). It's first foldMap(as, endoMonoid[B])(f.curried) which is called and then (z). The first returns B => B and called with the second returns B.
In functional programmming, there are two important methods named foldLeft and foldRight. Here is the implementation of foldRight
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tails: List[A]) extends List[A]
def foldRight[A, B](ls: List[A], z: B)(f: (A, B) => B): B = ls match {
case Nil => z
case Cons(x, xs) => f(x, foldRight(xs, z)(f))
}
And here is the implementation of foldLeft:
#annotation.tailrec
def foldLeft[A, B](ls: List[A], z: B)(f: (B, A) => B): B = ls match {
case Nil => z
case Cons(x, xs) => foldLeft(xs, f(z, x))(f)
}
}
My question is: I read from many documents, they often put order of f function is: f: (B, A) => B instead of f: (A, B) => B. Why this definition is better? Because if we use otherwise way, it will have same signature with foldLeft, and it will be better.
Because foldLeft "turns around" the cons structure in its traversal:
foldRight(Cons(1, Cons(2, Nil)), z)(f) ~> f(1, f(2, z))
^ ^
A B
foldLeft(Cons(1, Cons(2, Nil)), z)(f) ~> f(f(z, 2), 1)
^ ^
B A
And since it visits the conses in opposite order, the types are also traditionally flipped. Of course the arguments could be swapped, but if you have a non-commutative operation, and expect the "traditional" behaviour, you'll be surprised.
...if we use otherwise way, it will have same signature with foldLeft, and it will be better.
No, I think that would not be better. If they had the same signature then the compiler would not be able to catch it if you intend to use one but accidentally type in the other.
The A/B order is also a handy reminder of where B (initial or "zero") value goes in relationship to the collection of A elements.
foldLeft: B-->>A, A, A, ... // (f: (B, A) => B)
foldRight: ... A, A, A<<--B // (f: (A, B) => B)
I tried to write the following method for concatenating 3 lists together:
def f[A]: List[A] => List[A] => List[A] => List[A] = _ ++ _ ++ _
But got this compile-time error message:
<console>:7: error: missing parameter type for expanded function
((x$1, x$2, x$3) => x$1.$plus$plus(x$2).$plus$plus(x$3))
def f[A]: List[A] => List[A] => List[A] => List[A] = _ ++ _ ++ _
Is it possible to write it more concisely than the following:
scala> def f[A](xs: List[A], ys: List[A], zs: List[A]) = xs ++ ys ++ zs
f: [A](xs: List[A], ys: List[A], zs: List[A])List[A]
I know at least 2 ways to do it:
def f[A]: List[A] => List[A] => List[A] => List[A] =
a => b => c => a ++ b ++ c
def f2[A]: (List[A], List[A], List[A]) => List[A] =
_ ++ _ ++ _
val l1 = List(1)
val l2 = List(2)
val l3 = List(3)
println(f(l1)(l2)(l3))
println(f2(l1, l2, l3))
Your original _ ++ _ ++ _ is a placeholder for function with 3 parameters, but your f is curried function TypeA => TypeB => TypeC => TypeD (all types are equal to List)
So of you still want to use _ ++ _ ++ _ you need to transform your function to 3-input function (or function value of Tuple3 => something)
The problem you're having is due to the variety of ways that in Scala functions can be defined. First there are the "normal" non-curried functions with a signature like (T1, T2, ...) => RetType.
Then there are curried functions of the form T1 => T2 => ... => RetType which is essentially a chain of higher order 1-argument functions returning other 1-argument functions and the end of the chain returns the actual return value. For why this is useful, google for something like "scala curried functions".
The expression _ <someoperator> _ <someoperator> _ ... returns non-curried functions because those are the default in Scala. Therefore, if you declare foo to be returning T1 => T2 => ... => RetType but you actually return (T1, T2, ...) => RetType, the type signatures will mismatch and scalac will complain.
The solution is to either use both a curried signature as well as a curried function as the return value:
def foo1[T]: List[T] => List[T] => List[T] =
a => b => a ++ b
or use an uncurried signature and an uncurried return value:
def foo2[T]: (List[T], List[T]) => List[T] =
_ ++ _
the latter of which is the equivalent of:
def foo2[T]: (List[T], List[T]) => List[T] =
(a, b) => a ++ b
Yet another alternative is to have Scala convert your uncurried function into a curried one:
def foo2[T]: List[T] => List[T] = (_ ++ _).curried
...but, due to reasons that are out of the scope of this question, the type inferencer won't be able to be of much use, so you have to annotate and lose the concise nature of _ in the first place:
def foo2[T]: List[T] => List[T] = ((_: List[T]) ++ (_: List[T])).curried
In Haskell, liftM2 can be defined as:
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do
x1 <- m1
x2 <- m2
return $ f x1 x2
I'd like to translate this to Scala. My first attempt was the following:
def liftM2[T1, T2, R, M[_]](f: (T1, T2) => R)(ma: M[T1], mb: M[T2]) : M[R] = for {
a <- ma
b <- mb
} yield f(a, b)
This fails in what I guess is the most obvious way possible: "value flatMap is not a member of type parameter M[T1]". Right, I haven't indicated that M[_] is some kind of monad. So the next thing I tried was to define some structural type like:
type Monad[A] = {
def flatMap[B](f: (A) => Monad[B]): Monad[B]
}
... and to have M[A] <: Monad[A]. But that doesn't work, because Scala doesn't have recursive structural types.
So the next few things I tried involved gyrations similar to M[A] <: FilterMonadic[A, _]. Those all failed, probably because I wasn't able to figure out the right implicit-fu for CanBuildFrom.
The most closely-related question I could find here on StackOverflow was this one, touching both on recursive structural types and how to mimic Haskell's typeclasses in Scala. But that approach requires defining an implicit conversion from each type you care about to the trait defining the typeclass, which seems terribly circular in this case...
Is there any good way to do what I'm trying to do?
The usual way to encode type classes in Scala turns out to follow Haskell pretty closely: List doesn't implement a Monad interface (as you might expect in an object-oriented language), but rather we define the type class instance in a separate object.
trait Monad[M[_]] {
def point[A](a: => A): M[A]
def bind[A, B](ma: M[A])(f: A => M[B]): M[B]
def map[A, B](ma: M[A])(f: A => B): M[B] = bind(ma)(a => point(f(a)))
}
implicit object listMonad extends Monad[List] {
def point[A](a: => A) = List(a)
def bind[A, B](ma: List[A])(f: A => List[B]) = ma flatMap f
}
This idea is introduced in Poor Man's Type Classes and explored more deeply in Type Classes as Objects and Implicits. Notice that the point method could not have been defined in an object-oriented interface, as it doesn't have M[A] as one of it's arguments to be converted to the this reference in an OO encoding. (Or put another way: it can't be part of an interface for the same reason a constructor signature can't be represented in an interface.)
You can then write liftM2 as:
def liftM2[M[_], A, B, C](f: (A, B) => C)
(implicit M: Monad[M]): (M[A], M[B]) => M[C] =
(ma, mb) => M.bind(ma)(a => M.map(mb)(b => f(a, b)))
val f = liftM2[List, Int, Int, Int](_ + _)
f(List(1, 2, 3), List(4, 5)) // List(5, 6, 6, 7, 7, 8)
This pattern has been applied extensively in Scalaz. Version 7, currently in development, includes an index of the type classes.
In addition to providing type classes and instances for standard library types, it provides a 'syntactic' layer that allows the more familiar receiver.method(args) style of method invocation. This often affords better type inference (accounting for Scala's left-to-right inference algorithm), and allows use of the for-comprehension syntactic sugar. Below, we use that to rewrite liftM2, based on the map and flatMap methods in MonadV.
// Before Scala 2.10
trait MonadV[M[_], A] {
def self: M[A]
implicit def M: Monad[M]
def flatMap[B](f: A => M[B]): M[B] = M.bind(self)(f)
def map[B](f: A => B): M[B] = M.map(self)(f)
}
implicit def ToMonadV[M[_], A](ma: M[A])
(implicit M0: Monad[M]) =
new MonadV[M, A] {
val M = M0
val self = ma
}
// Or, as of Scala 2.10
implicit class MonadOps[M[_], A](self: M[A])(implicit M: Monad[M]) {
def flatMap[B](f: A => M[B]): M[B] = M.flatMap(self)(f)
def map[B](f: A => B): M[B] = M.map(self)(f)
}
def liftM2[M[_]: Monad, A, B, C](f: (A, B) => C): (M[A], M[B]) => M[C] =
(ma, mb) => for {a <- ma; b <- mb} yield f(a, b)
Update
Yep, its possible to write less generic version of liftM2 for the Scala collections. You just have to feed in all the required CanBuildFrom instances.
scala> def liftM2[CC[X] <: TraversableLike[X, CC[X]], A, B, C]
| (f: (A, B) => C)
| (implicit ba: CanBuildFrom[CC[A], C, CC[C]], bb: CanBuildFrom[CC[B], C, CC[C]])
| : (CC[A], CC[B]) => CC[C] =
| (ca, cb) => ca.flatMap(a => cb.map(b => f(a, b)))
liftM2: [CC[X] <: scala.collection.TraversableLike[X,CC[X]], A, B, C](f: (A, B) => C)(implicit ba: scala.collection.generic.CanBuildFrom[CC[A],C,CC[C]], implicit bb: scala.collection.generic.CanBuildFrom[CC[B],C,CC[C]])(CC[A], CC[B]) => CC[C]
scala> liftM2[List, Int, Int, Int](_ + _)
res0: (List[Int], List[Int]) => List[Int] = <function2>
scala> res0(List(1, 2, 3), List(4, 5))
res1: List[Int] = List(5, 6, 6, 7, 7, 8)