Hola, teniendo en cuenta que runState:: s->(a,s) , que get recupera el estado y put permite sobreescribir el estado actual, llegué al resultado con lo siguiente:
Cuando arranca la ejecución, el estado e es 5 (es el valor con el que se llamó al runState).
Al hacer a <- get en el bloque do, se está recuperando el estado y asignandole nombre a. Entonces a=5
Con el put x, se sobreescribe el estado con el valor del primer elemento de la lista. Entonces e=1
b hace la llamada recursiva con el resto de la lista. Entonces b no ha sido deteminado aún
Queda pendiente retornar a+b =
Paso 2:
a = 1, e = 10, b = foo [3,6], queda pendiente retornar a+b
Paso 3:
a = 10, e = 3, b = foo [6], queda pendiente retornar a+b
Paso 4:
a = 3, e = 6, b = 0, a+b = 3
En este punto tenemos a+b y es el valor de retorno de la función, entonces es lo que recibe b en el paso 3.
Ahora el paso 3 ejecuta a+b que retorna 13, y es el valor de b en el paso 2.
En el paso 2 se ejecuta a+b que retorna 14, y es el valor de b en el paso 1.
El paso 1 ejecuta a+b que es 19. El valor de e simplemente se va pasando, por eso queda con el último valor que es 6.
Tengo entendido que runState devuelve una tupla con el valor de retorno de la función interna y el estado. En este caso coincide con la salida (19,6).
No se si está bien el razonamiento, comparto para que me corrijan y afianzar conocimientos.
Gracias, Saludos.