Я не уверен, почему этот вопрос помечен с помощью SML, но поскольку это так, вот как это можно сделать в SML:
Во-первых, это идиоматическое решение, которое вы явно избегаете:
fun mapmap f = map (map f)
(Вы могли бы написать val mapmap = map o map
, если бы не ограничение значения ML .)
И если вы 'Я хотел бы написать mapmap
, используя явную рекурсию:
fun mapmap f [] = []
| mapmap f (xs::xss) = map f xs :: mapmap f xss
and map f [] = []
| map f (x::xs) = f x :: map f xs
Одна из причин, почему эту функцию трудно написать с помощью одной явно рекурсивной функции, заключается в том, что стек вызовов используется для двух вещей:
- Сбор результатов каждого внутреннего списка и
- Сбор результатов внешнего списка.
Одно из этих применений стека вызовов можно превратить вявный стек в аккумулирующем аргументе.Вот как, например, определяется хвостовая рекурсия rev
:
fun rev xs =
let fun aux [] acc = acc
| aux (x::xs) acc = aux xs (x::acc)
in aux xs [] end
Аргумент накопления аналогично не нужен в интерфейсе к mapmap
, поэтому он может быть скрыт во внутренней вспомогательной функции.Таким образом, единственная функция, которая выполняет явную рекурсию как во внутреннем, так и во внешнем списке, усложняется этой явной бухгалтерией:
fun mapmap f xss =
let fun aux f [] _ = []
| aux f ([]::xss) ys = rev ys :: aux f xss []
| aux f ((x::xs)::xss) ys = aux f (xs::xss) (f x :: ys)
in aux f xss [] end