gluon icon indicating copy to clipboard operation
gluon copied to clipboard

std function to print un-Showable types like the REPL does

Open lilyball opened this issue 7 years ago • 3 comments

The REPL seems to be able to print everything, but looking through the standard library documentation, I don't see how to print things that aren't Show. It would be nice if there was some way to convert arbitrary values into String in the same way the REPL does.

For example, I'm going through the book right now and I ran into the following example:

// type <identifier> <identifier>* = <type> in <expression>
type MyOption a = | None | Some a
let divide x y : Int -> Int -> MyOption Int =
    if (x / y) * y == x then
        Some (x / y)
    else
        None
in divide 10 4

This example can't be pasted into the REPL, so I put it in a file, and I can "run" that file, but there's no output. I wanted to tweak it to show me the results, but I don't see anything I can put on that last line to give me the expected output None.

lilyball avatar Jun 26 '18 22:06 lilyball

It isn't possible to print the value exactly how the repl does it since a function as described wouldn't have any type information available. Because of that the displayed value won't show Some None etc, it will only display the tag of the variant 0, 1, 2 .... (The repl does know about the type and can therefore do a pretty good job).

Basically we just add another function like the trace function in std.debug https://github.com/gluon-lang/gluon/blob/master/vm/src/debug.rs which uses format! instead.

Marwes avatar Jun 27 '18 11:06 Marwes

Could we do something funky like have a special implicit type like

#[implicit]
type DebugShow a = { debugShow : a -> String }

and then have the compiler synthesize an implementation of this for every type that you try to call it with?

Or alternatively, and I have no idea how Gluon macros actually work, but maybe have a compiler-provided macro dump! that synthesizes the output right there using the type information available to the compiler.

lilyball avatar Jun 27 '18 18:06 lilyball

The issue is this

let my_polymorphic_function x : a -> () =
    debug_show x // Since types are erased we have no idea what the type of the value is here
    ()

my_polymorphic_function "abc"
my_polymorphic_function 1
my_polymorphic_function { x = 1, y = 2 }

and then have the compiler synthesize an implementation of this for every type that you try to call it with?

This would be possible if functions were monomorphized but currently generics are just type erased (so there is only one instance of each function which can accept any type). While monomorphization works well for Rust, gluon's support for higher ranked types would actually make it impossible to monomorphize functions in general so it wouldn't fix this problem either (at least not completely).

With https://github.com/gluon-lang/gluon/pull/553 it will be possible to do #[derive(Show)] which should improve this a bit as well.

Marwes avatar Jun 27 '18 19:06 Marwes