Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unresolved flex record (need to know the names of ALL the fields in this context)

I've been trying to create a function with a tuple-list as an argument but I keep getting the error: "unresolved flex record (need to know the names of ALL the fields in this context)" My code is:

fun convert d = ( (map (#1) d) , (map (#2) d) );

This is basicaly trying to convert a list of pairs into a pair of lists.I've also tried to declare the type of d as :('a * 'b) list but that resulted in even more errors. I assume that this has something to do with the unknown size of the tupple and could use some help on how to make it known.

like image 914
giodude Avatar asked Nov 21 '12 16:11

giodude


1 Answers

I suspect that the issue you ran into with annotating the type of d was actually just that you weren't surrounding the annotation with parens, this works for me:

fun convert (d : ('a * 'b) list) = ( (map (#1) d) , (map (#2) d) )

However, this isn't great SML style. Using #1, #2, #n and so on is somewhat discouraged since it leads to issues like this, where you've lost some of the usual succintness that type inference gives you.

Instead, you can define some explicit selection functions for pairs:

fun first  (a, _) = a
fun second (_, b) = b

fun convert d = (map first d, map second d)

(Note that I've also dropped some superfluous parenthesis from the body of convert, since function application has higher precedence then tuple construction, and I've also dropped the semi-colon which is only really necessary when sequencing imperative code or when typing code into the REPL)

This is a pretty good style guide for Standard ML, from a course at Harvard (or maybe Tufts). An older version of that doc mentioned this specifically under "Common mistakes to avoid".

Avoid #1 and #2

Some beginners pick up the idea that a good way to get the second element of a pair p is to write #2 p.

This style is not idiomatic or readable, and it can confuse the type checker. The proper way to handle pairs is by pattern matching, so

fun first (x, _) = x
fun second (_, y) = y

is preferred, and not

fun bogus_first p = #1 p (* WRONG *)
fun bogus_second p = #2 p

(For reasons I don’t want to discuss, these versions don’t even type-check.)

If your pair or tuple is not an argument to a function, use val to do the pattern matching:

val (x, y) = lookup_pair mumble

But usually you can include matching in ordinary fun matching.

like image 186
michiakig Avatar answered Sep 19 '22 09:09

michiakig