Coerce polymorphic variant with constraints to string

Either I’ve found a compiler bug or I’m trying to do something so stupid the compiler won’t let me. :wink:

tl;dr in playround

Directly from the docs I can coerce a polymorphic variant to a string:

type company = [#Apple | #Facebook]
let theCompany: company = #Apple

let message = "Hello " ++ (theCompany :> string)

I can turn this into a lower bounded variant as follows, if I specify the type of the specific instance of the lower bounded variable:

type company<'a> = [> #Apple | #Facebook] as 'a
let theCompany: company<[#Apple | #Facebook | #Google]> = #Apple

let message = "Hello " ++ (theCompany :> string)

However, if I leave the generic as a lower bounded variant, it fails to compile:

type company<'a> = [> #Apple | #Facebook] as 'a
let theCompany: company<'a> = #Apple

let message = "Hello " ++ (theCompany :> string)

I don’t really have any context to provide because I’m just playing around to see how far I can push the language. :joy: I have it in mind I can use some of this for some generic database bindings, but I’m not actively trying to do anything with it right now.


AFAIK, the issue is that only polyvars without payloads can be coerced into strings. The type [> #Apple | #Facebook] as 'a allows for the possibility of a polyvar like #Google(100), which doesn’t compile to a JS string.

I don’t think there’s any language-level way to express a polyvar type as “only variants without payloads.” I think for practical situations, you’d be better off just using plain strings.


I have wanted this polyvar type expression too but it seems like at that point maybe better to use a module functor as typeclass and require a toString/fromString etc?


1 Like

Aha, that makes perfect sense, thanks for the explanation.

I’m experimenting with functors as well, so we’ll see what I can break next!