Search code examples
typesocamlreason

Printing User-Defined types in ReasonML


Is there an easy way to generically print user-defined types or nested lists in ReasonML?

Context: I'm working on writing check expect procedures for students for an intro CS course I TA and we're using Reason this year for the first time. When the check expect fails I would like to print out both the expected and actual output, but I can't figure out how to effectively print out the result without knowing ahead of time what the type of the arguments is going to be, particularly nested lists and user defined types.

My current workaround: I have written out a different check expect procedures depending on the type they take in (ex. checkExpectListLists which maps over each of the nested lists and recursively prints the arguments.)

Potential help: Sketch.sh is able to evaluate and print out the result of function calls even with user defined types. Does anyone know how they do this/how I can use that functionality in my own check expect printing?

Thanks!


Solution

  • An important point to keep in mind is that due to type-erasure, there is not enough information to pretty-print any user-defined types at runtime with compiled code. At best, you can print the memory representation. With some clever trick you could try to map this memory representation to your predefined type. However, this sounds like it could yield utterly maddening error message for your students.

    Thus, you need to keep more information about your student codes before evaluation.

    One way to do it is to use a toplevel session, like Sketch is doing. Since the Repl has access to the type definitions, it can use this information to pretty-print any user defined types. The easiest way to setup is to launch an OCaml Repl process, and use it to both eval and print the student code. A little more involved possibility, but yielding more control ultimately, would be to use directly OCaml's compiler library. Then you have to initialize a REPL session, add some flux redirections. Once it is done, you can eval your student code phrase by phrase, looks at existing values at the environment...

    Another orthogonal way would be to parse your student code and add pretty-printer to every type definitions. This can be done using the ppx infrastructure. For instance, you could write a custom ppx that adds a deriving annotation to every type definitions. You could also seek the function being tested and adds some instrumentation to the function.