Skip to main content

for comprehension

If a type has flatMap and map (or it has flatMap and map as its extension methods), you can use for comprehension instead of using nested flatMaps and map.

flatMap and map

In for comprehension, <-s (left arrows) are flatMap except for the last one. The last <- is map.

for {
b <- foo(a)
c <- bar(b)
d <- baz(c)
} yield b + c + d + e

is equivalent to

foo(a).flatMap { b =>
bar(b).flatMap { c =>
baz(c).map { d =>
b + c + d + e
}
}
}

So

for {
b <- foo(a) // flatMap { b =>
c <- bar(b) // flatMap { c =>
d <- baz(c) // map { d =>
} yield b + c + d + e

for {
b <- foo(a)
c <- bar(b)
} yield b + c + d

is equivalent to

foo(a).flatMap { b =>
bar(b).map { c =>
b + c + d
}
}

So

for {
b <- foo(a) // fatMap { b =>
c <- bar(b) // map { c =>
} yield b + c + d

for {
b <- foo(a)
} yield b + c

is equivalent to

foo(a).map { b =>
b + c
}

So

for {
b <- foo(a) // map { b =>
} yield b + c

It means the following one is meaningless

for {
b <- foo(a)
} yield b

because it's equivalent to

foo(a).map { b =>
b
}

which does nothing.

So you can simply do this instead.

foo(a)

A single <- in for-comprehension could be flapMap as well depending on the return type of the function.

for {
b <- foo(a)
} yield bar(b)

where bar(b) returns the same type as foo(a)'s.

It is equivalent to

foo(a).flatMap { b =>
bar(b)
}

So

for {
b <- foo(a) // foo(a).flatMap { b =>
} yield bar(b)

If your for-comprehension has only one <-, you can simply use map or flatMap instead of for-comprehension, as it doesn't add much readability for a single map or flatMap case.