tags:

views:

331

answers:

3

After a command is executed in SML, "it" is returned which has the data and the type returned from the command. For example:

false;  
val it = false : bool

Let's say I have a binding in a program like so:

 val argsToOutput = (map (fn (Absyn.var_exp(n)) => 
                               (lookupReference env n)) exps)

Is there a way to print the value and datatype of "argsToOutput" (in the middle of the program) in a similar fashion to how "it" is printed out?

+1  A: 

SML is statically-typed, so the type of any value in the program is statically known at compile time. I'm not sure what you want when you want to "print it out".

Maybe you can't figure out by looking at the code yourself what the type of something is. When you define a value at the top level into the interpreter, either directly or if you load a file using use "whatever.sml";, the interpreter will tell you the type that is inferred for that value.

Alternately, if you have a piece of code, you can post it (and also any code it depends on) here and we can help you figure out what type a particular value in it has.

If you want to ensure that a particular value is a certain type, you can use type guards: (expression : type) is the same thing as expression, except that during type checking it will make sure that that expression is that type.

If you want to somehow get type information at runtime, I don't think you can, and you shouldn't need to, because it's already known at compile time.

newacct
The problem is I don't know what the type is. I'm working on code for a class and we use CM.make to "compile" a set of 6 files. I'm struggling to figure out what datatype (and values) is actually being bound to a certain binding. Its impractical to post all the code in this case. Any other ideas?
I dunno. Is there no way you could load the files into the interpreter? Alternately, you could go in and put type annotations on all function arguments and return types and variables. I know that part of the type inference in ML is that you don't need to declare types for your variables, but sometimes it's nice for debugging. Also, maybe you could try putting in a type guard for your value anyway, and when it doesn't type check, the error message might give you some idea what the type really is.
newacct
+1  A: 

You could do:

 val argsToOutput = (map (fn (Absyn.var_exp(n)) => 
                               (lookupReference env n)) exps)
 ...
 in
   (print (argsToOutput); 2 )
 end

where instead of 2 you have the value of your let body. Odds are print will barf on argsToOutput, but it will give you the type found where the type expected is string.

When I have had to print out a datatype's value, I created a tostring() function that took the datatype, and transformed it into a string. It took some work because it had some nested datatypes, but was very valuable afterwards because it worked on all vars of that type.

Kai
+1  A: 

Is there a way to print the value and datatype of "argsToOutput" (in the middle of the program)

No. It works at toplevel because the compiler retains the type from the compilation phase. It won't work on arbitrary expressions pulled out of function bodies. BUT if you are lucky enough to have an expression whose value is independent of the function, you can pull it out and write a val binding at top level and get what you wanted:

- val thing = hd [1, 2, 3];
val thing = 1 : int

This is poor consolation since it covers few cases of interest.

I think you may want to search for the answers to other FAQs:

  1. How can I get my ML programs to type-check?
  2. How can I be sure of the type of a subexpression in a well-typed ML program?
  3. In an ML program, how can I print a value for debugging?

(The answers are ugly.)

Norman Ramsey