Yes, the fluent chain will allow more back-propagation than the approach I described. Based on the desugaring to statements:
let d = LayerBuilder.buildFold(c, Dense(...))
let e = LayerBuilder.buildFold(d, Dense(...))
The type of d needs to be fully determined (all the way to a concrete type; no remaining type variables) before the type checker will start working on the initializer expression for e. How e type-checks cannot affect how d type checks. Here's an example of the backward propagation in a fluent interface:
struct X<T> {
func f() -> Y<T> { .init() }
}
struct Y<T> {
func g() -> T? { nil }
}
let a: Int? = X().f().g()
Here, Int backward-propagates to the generic argument type of X. If I did that "function-builder-style" as we are discussing, it would fail to type check because
let x = X()
cannot determine the generic argument of X.
Doug