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.

2 Likes

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.

2 Likes

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?

A

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!