Creating a partially applied function leads to error contains the non-generalizable type variable(s): '_weak1

Heya!

I’m using Dream together with Tyxml and I have this ugly function I’d like to move to a helper function to make it more readable

let string_of_html = Format.asprintf "%a" (Html.pp_elt ()) 

However, it runs into issues with the type variable being non-generalizable

error contains the non-generalizable type variable(s):'_weak.

When I use Format.asprintf "%a" (Html.pp_elt ()) in a context, it deduces the variable correctly, but I am wondering if there is a way to type string_of_html so I can use that instead?

Add a parameter:

let string_of_html x = Format.asprintf "%a" (Html.pp_elt ()) x 
1 Like

Add a parameter:

let string_of_html x = Format.asprintf "%a" (Html.pp_elt ()) x 

Ah it was that simple. I could’ve sworn I tried it haha. Thank you

To expand on @emillon’s answer, this is the infamous “value restriction”: let-bound values are only generalized (made polymorphic) if the right-hand side of the = is syntactically a “value” (eg a function). In particular, a function application is not one and so the definition is not generalized.

Eta-expansion (“adding a parameter”) can sometimes be used to work around this restriction, but one should keep in mind that the application in the right-hand side will now be executed each time that the bound variable is invoked, instead of only once when the variable is bound.

Cheers,
Nicolas

1 Like

I feel that this sentence is a bit too confusing the way it is worded. Indeed, eta-expanding does not work around the value restriction. On the contrary, it triggers the value restriction (just by definition), thus allowing the compiler to generalize the type.

Thanks for the comment. My understanding of the English phrase “trigger a restriction” is that of not satisfying the condition defining the restriction. In that sense, I interpret “work around the restriction” or “avoid the restriction” as indicating a way to satisfy the condition in question. So I would interpret “triggering the value restriction” to mean exactly that the program fails to typecheck, which is the opposite of how you interpreted it :slight_smile: I may be wrong, clarification is welcome!

Cheers,
Nicolas

I would say “satisfy the restriction”: an eta expansion is a value so its type can be generalized.