Применение списка аргументов к функции карри с использованием foldLeft в Scala

Можно ли сделатьfoldLeft в списке аргументов, где начальное значение, переданное в сгиб, является полностью каррированной функцией, операторapply, а список - это список аргументов, передаваемых в функциюf?

Например, допустим, что f определяется как:

scala> val f = (i: Int, j: Int, k: Int, l: Int) => i+j+k+l
f: (Int, Int, Int, Int) => Int = <function4>

Что мы можем, конечно, использовать напрямую:

scala> f(1, 2, 3, 4)
res1: Int = 10

Или карри и применить аргументы по одному:

scala> f.curried
res2: Int => Int => Int => Int => Int = <function1>

scala> f.curried.apply(1).apply(2).apply(3).apply(4)
res3: Int = 10

На первый взгляд это выглядит как работа дляfoldLeft.

Моя первая попытка описать эту последовательностьapply с помощьюfoldLeft выглядит как:

scala> List(1, 2, 3, 4).foldLeft(f.curried)({ (g, x) => g.apply(x) })

Однако это приводит к следующей ошибке:

<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) })

Мое чтение сообщения об ошибке заключается в том, что вывод типа потребует некоторой подсказки дляg.

Решение, которое я ищу, оставляет все неизменным в моем исходном выражении, кроме типаg:

List(1, 2, 3, 4).foldLeft(f.curried)({ (g: ANSWER, x) => g.apply(x) })

Моей первой мыслью было, что здесь будет полезен тип объединения. Я видел, как Майлз Сабин выводил типы профсоюзов с помощью Curry-Howard, поэтому, если это первое предположение верно, то у меня, похоже, есть базовый механизм, необходимый для решения проблемы.

Тем не менее: даже если объединение типов является ответом, было бы полезно, если бы я мог сослаться на «Объединение всех типов от полностью карризованного типа функции до типа функции карри со всеми, кроме последнего предоставленного аргумента». Другими словами, способ превратить тип:

T1 => ... => Tn

в тип объединения:

(T1 => ... => Tn) |∨| ... |∨| (Tn-1 => Tn)

было бы полезно в качестве типа дляg выше.

ДелатьfoldLeft наList ограничивает обсуждение случаем, когдаT1 черезTn-1 все одинаковые. Обозначение как

(T1 =>)+ Tn

описал бы тип, который я хочу предоставить дляg.

Конкретный случай, о котором я спрашиваю, не требует сколь угодно длинных цепочек, поэтому мы можем предоставить границы для итератора, используя

(T1 =>){1,4} Tn

Забегая вперед, намереваясь сделать это для цепочек типов, которые не равны, тем не менее, возможно, некоторая магическая функция над типами, которая разбивает цепочку на множество всех суффиксов, более полезна:

Suffixes(T1 => ... => Tn)

Реализация этого сейчас выходит далеко за рамки моих возможностей в Scala. Будем благодарны за любые советы о том, как это сделать. Можно ли это сделать с помощью расширенного использования существующей системы типов Scala или с помощью плагина компилятора, или ни того, ни другого, я не знаю.

Как было отмечено в комментариях ниже, называть результат «тип объединения» не идеально подходит для этого варианта использования. Я не знаю, как еще это назвать, но это самая близкая идея, которая у меня есть на данный момент. Есть ли у других языков особая поддержка этой идеи? Как это будет работать в Coq и Agda?

Назвать эту проблему и понять, где она находится по отношению к более широкой картине (теории типов, разрешимости и т. Д.), Для меня важнее, чем иметь работающую реализациюANSWERХотя оба были бы хороши. Бонус указывает любому, кто может установить связь со Скалазом, Моноидами или Теорией категорий в целом.

Ответы на вопрос(3)

Ваш ответ на вопрос