Я бы определил это в терминах общей функции scanl
.Он похож на foldl
, но выдает список промежуточных результатов.Он работает почти как кумулятивная сумма, но с параметризацией оператора +
и элемента по умолчанию.Он не доступен в стандартной библиотеке, но с таким же успехом может быть.
fun scanl _ _ [] = []
| scanl f y0 (x::xs) =
let val y1 = f (x, y0)
in y1 :: scanl f y1 xs
end
, а затем:
val cumsum = scanl op+ 0
Есть ли способ реализовать это с помощью одной функциитолько?
Это зависит от того, что вы подразумеваете под «только одна функция».
Только одна функция вообще?cumsum
принимает только один список в качестве входных данных, и вам нужен дополнительный аргумент для отслеживания накопленной суммы.Поскольку функция, которая накапливает результат, не может быть cumsum
напрямую, вам нужны две функции.Так вы имеете в виду «одну именованную функцию помимо cumsum
»?Тогда scanl
или внутренняя вспомогательная функция Мэтта решит эту проблему.
Если вы можете определить cumsum
только с помощью функций стандартной библиотеки:
val cumsum = tl o rev o foldl (fn (x, y::ys) => x + y :: y :: ys) [0]
Тогда cumsum
становится единственной функциейчто вы объявляете.
И если вы можете определить cumsum
только с помощью одной функции стандартной библиотеки, я бы пошел с foldl
:
val cumsum = (fn (_::xs) => xs) (* tl *)
o foldl op:: [] (* rev *)
o foldl (fn (x, y::ys) => x + y :: y :: ys) [0]
Тогда cumsum
становитсяединственная функция, которую вы объявляете, и для этого вы использовали только одну именованную функцию стандартной библиотеки.(Если бы это не была функция стандартной библиотеки, вам нужно было бы объявить ее, а затем вы бы объявили две функции.)
Но это становится немного глупо.: -)