Но как это можно изменить, скажем, для создания нового списка совпадений, а не просто для их подсчета?
В этом случае вы хотите две модификации вашего текущего решения:
Вы хотите изменить шаблон вашего рекурсивного случая на тот, в котором вы можете извлечь всю тройку даты, если она совпадает. Прямо сейчас вы извлекаете только часть месяца для сравнения, отбрасывая остальные биты, поскольку вы просто хотите увеличить счетчик в случае совпадения месяца.
Результат функции должен быть не 1 + ...
, а скорее (x1,x2,x3) :: ...
.
Итак, быстрое решение:
fun dates_of_month ([], _) = []
| dates_of_month ((year,month,day) :: dates, month1) =
if month = month1
then (year,month,day) :: dates_of_month (dates, month1)
else dates_of_month (dates, month1)
Я изменил ...((_,x2,_) :: xs, m)
на ...((x1,x2,x3) :: xs, m)...
, и это сработало, но это похоже на кучу.
Вот две альтернативы Андреаса Россберга:
Использование let-in-end :
fun dates_of_month ([], _) = []
| dates_of_month (date :: dates, month1) =
let val (_, month, _) = date
in
if month = month1
then date :: dates_of_month (dates, month1)
else dates_of_month (dates, month1)
end
Использование as
:
fun dates_of_month ([], _) = []
| dates_of_month ((date as (_,month,_)) :: dates, month1) =
if month = month1
then date :: dates_of_month (dates, month1)
else dates_of_month (dates, month1)
А вот третий вариант, который абстрагирует рекурсию с помощью комбинатора списка более высокого порядка:
fun dates_of_month (dates, month1) =
List.filter (fn (_, month, _) => month = month1) dates