1

I have following code snippet:

  def traverse[E, A, B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
    es match {
      case Nil => Right(Nil)
      case h :: t => (f(h) map2 traverse(t)(f)) (_ :: _)
    }

the map2 function implementation:

  def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] =
    for {
      aa <- this
      bb <- b
    } yield (f(aa, bb))

What I do not understand is this code:

(f(h) map2 traverse(t)(f)) (_ :: _)

First, the function f will be apply to argument h. After it will call map2 function until it reached the Nil in List. What is the (_ :: _) function for? So weird function call.

softshipper
  • 32,463
  • 51
  • 192
  • 400
  • The `(_ :: _)` is the second argument to the `map2` function. You have one `Either` by applying `f` to the head of the list and one `Either` from the recursive call. The `map2` function will apply the list concatenation `(_ :: _)` if both `Either` are `Right`. – Harald Gliebe Mar 20 '17 at 13:10
  • I could change the code to: `f(h).map2(traverse(t)(f)) (_ :: _)`. Why do I need `(` in front of the first `f` why not like `f(h) map2(traverse(t)(f)) (_ :: _)`? With the `(` in front of `f` it is not clear, that `(_ :: _)` is the second argument of `map2`. So weird scala syntax. – softshipper Mar 20 '17 at 13:44
  • 1
    Because `map2` is used infix here. The equivalent `f(h).map2( traverse(t)(f) )( _::_ )` means the *curried* method is called with its two parameters – Bergi Mar 20 '17 at 21:48
  • This syntax `f(h).map2( traverse(t)(f) )( _::_ )` is much cleaner then I mentioned above. In math, everything in parentheses will be execute first, that because I confuse parentheses `(f(h) map2 traverse(t)(f)) (_ :: _)` by first and last `f`. How do you recognize that `map` is an infix? – softshipper Mar 21 '17 at 09:02

0 Answers0