Letâ€™s try and explain how we can arrive at that implementation using intuitions and some minor perusal of the API for List and Random!

## Step 1

Realize we want to â€śtransformâ€ť a list of values, into some other thing. If the â€śother thingâ€ť is a new `List`

, you would generally use `List.map`

. Letâ€™s assume we donâ€™t really want to change the generators themselves, so letâ€™s start with that:

```
combine generators =
List.map identity generators
```

## Step 2

Hm, the expected result isnâ€™t â€śjustâ€ť a `List`

, though, which is all that `List.map`

is capable of generating. We do have a slightly more flexible function in our arsenal, though - folding. Whichever way we fold, we can use it to create something else from a list by using a fold. Since our final type does have `List`

in its result type, and we want the generators to be in the same order as we feed them in, letâ€™s start by rewriting the previous attempt using a fold:

```
combine generators =
List.foldr (\item acc -> item :: acc) [] generators
```

Oh, that lambda looks like itâ€™s just the definition of the cons operator, so letâ€™s change that slightly. Generally being super concise isnâ€™t worth the trouble, but I feel like this is a pretty acceptable use of partial application for infix operators:

```
combine generators =
List.foldr (::) [] generators
```

## Step 3

Okay, the type signature doesnâ€™t match up - weâ€™re returning a `List`

rather than a `Generator (List a)`

. So, in our fold, rather than adding to a List, we want to add to a `Generator (List a)`

.

I generally find it helpful to get the â€śinitial accumulatorâ€ť figured out before figuring out the function to apply to it. In this case, we want the final result to be a `Generator (List a)`

so we want out initial accumulator to be of that type.

So, how can we create an Generator for an empty list as our initial accumulator? Ah, thereâ€™s a `constant`

function. Cool, letâ€™s try that. Since weâ€™re now working on getting the type signature to work out, letâ€™s add that in, too:

```
combine : List (Generator a) -> Generator (List a)
combine generators =
List.foldr (::) (Random.constant []) generators
```

## Step 4

So, we have a type mismatch for our accumulating function. Weâ€™re giving it a function `a -> List a -> List a`

but itâ€™s expecting a function `Generator a -> Generator (List a) -> Generator (List a)`

. So the goal is to find a way to change that first one into that second one.

When looking for a function, it helps to go look for a function that has a generalized form of the specific thing youâ€™re attempting to do.

In the most general terms, weâ€™re looking for something that takes a `a -> b -> c`

and gives us a `Generator a -> Generator b -> Generator c`

.

Turns out thereâ€™s a `Random.map2 : (a -> b -> c) -> (Generator a -> Generator b -> Generator c)`

. Lucky us!

```
combine : List (Generator a) -> Generator (List a)
combine generators =
List.foldr (Random.map2 (::)) (Random.constant []) generators
```

Granted, that explanation isnâ€™t great for someone with absolutely zero experience with FP. However, I think itâ€™s possible to explain it using some of the intuitions that people build up while working with functional programming, which to me seems a bunch simpler than saying â€śitâ€™s monad transformationâ€ť. Of course, different people learn in different ways, so your mileage may vary!