Disclaimer, this is part of an online course, but I have solved the homework. My question is about the pattern matching of records work?
So in the first function I do not have to specify the structure of the record
fun generateName (ls , name)=
case ls of
[] => name::[]
| x::xs =>
{
first= x,
middle= #middle name,
last= #last name
}
:: generateName(xs, name);
In this function I do. Otherwise I get a flex record error.
fun createName (f, name :{first:string, middle:string, last:string}) =
case f of
x =>
{
first= x,
middle= #middle name,
last= #last name
}
Even more confusingly this one gives no error
fun generateName2 (nms, name) =
let fun aux (ls, name, acc) =
case ls of
[] => name::acc
| x::xs =>
aux(xs, name,
{
first= x,
middle= #middle name,
last= #last name
} :: acc)
in
aux (nms, name, [])
end
When do I have to specify the record fields?
SML does not have row polymorphism, so the compiler needs to know all field names of a record.
In the functions that return lists, the recursion limits the possible types; if name
has the type R
, generateName (ls , name)
has the type R list
, and all the field names can be inferred from the non-empty recursive case.
The middle example does not have such a relationship between input and output, so unless you specify the input field names, SML does not know what they are.