Haskell выполнит так называемую ленивую оценку, что означает, что он будет работать только так, как он нужен слева направо (обычно). Итак, взяв ваш пример mystery [1, 2]
, Haskell сделает следующее:
sets ++ (map (x:) sets)
Что оценивается в:
mystery (2:[]) ++ (map (1:) sets)
На данный момент мы звоним mystery (2:[])
mystery ([]) ++ (map (2:) sets) ++ (map (1:) sets)
mystery ([])
вернет пустой список списков
[[]] ++ (map (2:) sets) ++ (map (1:) sets)
[[]] ++ (map (2:) mystery []) ++ (map (1:) sets)
Так что теперь Haskell попытается применить функцию (2:)
к списку, содержащему пустой список
[[]] ++ (2:[[]]) ++ (map (1:) sets)
[[]] ++ [[2]] ++ (map (1:) sets)
[[], [2]] ++ (map (1:) sets)
Здесь все становится немного более запутанным.
[[], [2]] ++ (map (1:) mystery (2:[]))
Это последнее sets
будет оценивать mystery (2:[])
[[], [2]] ++ (map (1:) (sets ++ (map (2:) sets)))
[[], [2]] ++ (map (1:) (mystery [] ++ (map (2:) sets))
[[], [2]] ++ (map (1:) ([[]] ++ (map (2:) mystery []))
[[], [2]] ++ (map (1:) ([[]] ++ (2:[[]]))
[[], [2]] ++ (map (1:) ([[]] ++ [[2]])
Теперь (1:)
будет применен к списку, который содержит пустой список, и список, содержащий 2:
[[], [2]] ++ (map (1:) ++ [[], [2]])
[[], [2]] ++ [[1], [1, 2]]
[[], [2], [1], [1, 2]]
Настоящая суть операции - в этих двух последних разделах. Haskell создает список наподобие [[], [2]]
, а затем добавляет его в начало каждого списка, чтобы сформировать [[1], [1, 2]]
.