¿Es posible hacer un foldLeft
en una lista de argumentos, donde el valor inicial proporcionado para el plegado es una función completamente curried, el operador es apply
y la lista es una lista de argumentos para pasar a la función f
?Aplicar una lista de argumentos a la función curried utilizando foldLeft en Scala
Por ejemplo, supongamos que f se define como:
scala> val f = (i: Int, j: Int, k: Int, l: Int) => i+j+k+l
f: (Int, Int, Int, Int) => Int = <function4>
cual podemos, por supuesto, utilizar directamente:
scala> f(1, 2, 3, 4)
res1: Int = 10
o el curry y aplicar los argumentos uno a la vez:
scala> f.curried
res2: Int => Int => Int => Int => Int = <function1>
scala> f.curried.apply(1).apply(2).apply(3).apply(4)
res3: Int = 10
A primera vista, esto parece un trabajo para foldLeft
.
Mi primer intento de describir esta secuencia de apply
usando foldLeft
parece:
scala> List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
Sin embargo, que produce el error siguiente:
<console>:9: error: type mismatch;
found : Int => Int => Int => Int
required: Int => Int => Int => Int => Int
List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })
Mi lectura del mensaje de error es que la inferencia de tipos necesitaría alguna pista para g
.
La solución Busco deja todo sin modificar en mi expresión original, excepto el tipo de g
:
List(1, 2, 3, 4).foldLeft(f.curried)({ (g: ANSWER, x) => g.apply(x) })
Mi primer pensamiento fue que un tipo de unión sería útil en este caso. He visto la derivación de sindicatos de Miles Sabin usando Curry-Howard, así que si esa primera corazonada es cierta, entonces parece que tengo la maquinaria básica requerida para resolver el problema.
Sin embargo: incluso si los tipos de unión son la respuesta, sería útil si pudiera referirme a "La unión de todos los tipos del tipo de función completamente currificado al tipo de la función curried con todo menos el último argumento proporcionado ". En otras palabras, una manera de convertir el tipo:
T1 => ... => Tn
en el tipo de unión:
(T1 => ... => Tn) |∨| ... |∨| (Tn-1 => Tn)
sería útil como el tipo de g
anteriormente.
Haciendo un foldLeft
en un List
limita la discusión a través de caso en T1
Tn-1
son todos iguales. Una notación como
(T1 =>)+ Tn
describiría el tipo que quiero prever g
.
El caso específico que estoy preguntando por no requiere cadenas de longitud arbitraria, por lo que podríamos proporcionar los límites en el iterador utilizando
(T1 =>){1,4} Tn
De cara a querer hacer esto para las cadenas de tipos que no están igualdad de condiciones, sin embargo, tal vez alguna función mágica sobre los tipos que las chuletas de la cadena en el conjunto de todos los sufijos es más útil:
Suffixes(T1 => ... => Tn)
la implementación de este es mucho más allá de mis capacidades Scala en este momento. Cualquier sugerencia sobre cómo hacerlo será apreciada. Si esto se puede hacer con un uso avanzado del sistema de tipos existente de Scala o mediante un plugin de compilación o ninguno, no lo sé.
Como se ha señalado en los comentarios a continuación, llamar al resultado "tipo de unión" no es perfecto para este caso de uso. No sé cómo llamarlo, pero esa es la idea más cercana que tengo en este momento. ¿Otros idiomas tienen un apoyo especial para esta idea? ¿Cómo funcionaría esto en Coq y Agda?
Nombrar este problema y entender dónde se encuentra con respecto a la imagen más grande (de la teoría de tipos, decidability, etc.) es más importante para mí que tener una implementación operativa de ANSWER
, aunque ambas serían buenas. Puntos de bonificación para cualquier persona que pueda establecer conexiones con Scalaz, Monoids o la teoría de categorías en general.
no estoy seguro de que los tipos de unión son el camino a seguir aquí. Parece que buscas una operación de curry sobre los argumentos representados como HList. Creo que algo así es factible. De todos modos, es un problema interesante ... Investigaré y responderé correctamente si se me ocurre algo factible. –
Guau, gracias, Miles. Me encantaría saber qué opinas de este problema. Estoy de acuerdo en que los tipos de unión, per se, parecen no ser exactamente lo que se necesita en esta situación. –
@MilesSabin He aclarado mi pregunta y he presentado algunos formularios que una respuesta podría tomar. Todavía no estoy seguro de si esto es o debería ser posible, pero de cualquier forma este ha sido un buen ejercicio para hablar sobre esto. –