Search code examples
functional-programmingsml

How does SML pattern matching records work


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?


Solution

  • 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.