Может быть, это поможет, если мы раскладываем функцию в стиль карри, у которого нет вложенных шаблонов, в функции foo ниже есть только 3 (не вложенных) шаблона,
fun foo [] [] [] = []
| foo (hd1::tl1) (hd2::tl2) (hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| foo _ _ _ = raise BadTriple
and zip3 (l1, l2, l3) = foo l1 l2 l3
этоЛегко увидеть каждый отдельный шаблон, когда мы используем ключевое слово as, справа от каждого , поскольку является шаблоном.
fun zip3 (l1 as [], l2 as [], l3 as []) = []
| zip3 (l1 as hd1::tl1, l2 as hd2::tl2, l3 as hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| zip3 _ = raise BadTriple
Итак, почему мы рассматриваем это вложение?
мы можем добавить начальный аргумент as list_triple и увидеть, что на самом деле у нас есть шаблоны внутри шаблона.
fun zip3 (list_triple as (l1 as [], l2 as [], l3 as [])) = []
| zip3 (list_triple as (l1 as hd1::tl1, l2 as hd2::tl2, l3 as hd3::tl3)) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
без as и неиспользуемые переменные будут выглядетьгораздо приятнее.
fun zip3 ([], [], []) = []
| zip3 (hd1::tl1, hd2::tl2, hd3::tl3) = (hd1, hd2, hd3)::zip3(tl1, tl2, tl3)
| zip3 _ = raise BadTriple