lo tolmencre
lo tolmencre

Reputation: 3954

tuple access: Can't find a fixed record type

I wrote a function that is supposed to receive a list of tuples. I access the components of the tuples with # and the code compiles:

fun recheck ([], n) = []
  | recheck (h::t, n) = 
    if ((#1 h) *  (#1 h)) +  ((#2 h) * (#2 h)) = n then
    h::recheck(t, n)
    else
    recheck(t, n)

But another function that basically does the same thing, namely receiving a list of tuples and accessing those, causes an error.

fun validate ([]) = true
  | validate (h::t)  = 
    if 1 = (#1 h) then
    true
    else
    false

Can't find a fixed record type.   Found near #1

What is the difference here and why does the latter cause an error?

Edit

The first function actually does not compile on its own.

But this entire snippet does:

fun drop ([], n) = []
  | drop (h::t, 0) = h::t
  | drop (h::t, n) =
    drop(t, n-1) 

fun sts_linear (y, n) =
  if y < (Math.sqrt(n)+1.0) then
      let
      (* x^2 + y^2 = n => x = sqrt(n-y^2) *)
      val x = Math.sqrt(n - (y * y));
      val xr  = Real.realRound(x);
      in
  if (abs(x - xr) < 0.000000001)  then
          [(Real.trunc xr, Real.trunc y)]@sts_linear (y+1.0, n)
      else
          (
        []@sts_linear (y+1.0, n)
          )
      end
  else []

fun recheck ([], n) = []
  | recheck (h::t, n) =
    if ((#1 h) *  (#1 h)) +  ((#2 h) * (#2 h)) = n then
    h::recheck(t, n)
    else
    recheck(t, n)

fun sts (n) =
  (
    let
        val pairs = sts_linear(0.0, Real.fromInt n);
    in
        recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
    end
  )

Upvotes: 1

Views: 220

Answers (2)

matt
matt

Reputation: 5624

Trying to minimize this down, as I have seen the following work in SML/NJ and i'm not aware of it actually being a compiler extension

val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};

There is an awkward construct from a compiler error perspective not many languages have errors that work in this fashion, because the function is valid, but produces a type error unless an invocation of the function exists to resolve the type of 'record', thus to resolve the error more code must be added.

fun getFoo(field) = fn record => field record;

Without the following actual calling of the getX the compiler cannot determine the type of record of which the complete type information of ALL fields of the record must be known to the compiler, not just the #x field.

let val getX = getFoo(#x);
    val x1 = getX(p1);
    val x2 = getX(p2);
    val x3 = getFoo(#x)(p3);
in () end;

while the following commented out snippet results in an error because the types of p1 and p3 are different, and so different invocations of getFoo are required

(*
let val getX = getFoo(#x);
    val x1 = getX(p1);
    val x3 = getX(p3);
in () end;
*)

and the following is insufficient since it never resolves the record.

let val getX = getFoo(#x) in () end;

Upvotes: 0

John Coleman
John Coleman

Reputation: 52008

Your first code doesn't compile, at least with SML/NJ:

enter image description here

If you got it to compile then it must have been in a nonstandard extension of SML.

The problem with both of your definitions is that there is no polymorphic idea of a tuple of arbitrary arity in SML. You can write functions to work on lists of pairs. You can write functions to work on lists of triples. But -- you can't write functions to work simultaneously on lists of pairs and lists of triples (at least if your function tries to do things with these pairs/triples as tuples).

One solution is to get rid of # and use pattern-matching to extract the components:

fun validate [] = true
|   validate ((x,y)::t)  = 
        if x = 1 then
            true
        else
            false

But, if you really want to write a function which can polymorphically apply to either lists of pairs or list of triples (or quadruples,...), the easiest thing to do is to represent the pairs, triples, etc. as lists rather than tuples. Lists which contains lists of nonspecified size are not a problem in SML.

Upvotes: 2

Related Questions