I am puzzled as to why the 3rd function would not work :
let generate1 = id
let generate2 = let a = 1
id
let generate3 = printfn "hi"
id
while the first 2 are fine, the last one spits out
error FS0030: Value restriction. The value 'generate3' has been inferred to have generic type
val generate3 : ('_a -> '_a)
Either make the arguments to 'generate3' explicit or, if you do not intend for it to be generic, add a type annotation.
I won’t attempt to explain value restriction, but I will attempt to sort out the semantic differences between these three values.
generate1is just an alias forid, so we’re good there.generate3does some computations before returningid, hitting value restriction.Then why doesn’t
generate2hit value restriction likegenerate3? Because the compiler can see thatlet x = 1 in idis semantically equivalent to justid:1is a constant expression andxnot used in the body of thelet ... in ...expression, so the compiler can and does throw them away. On-the-other-hand, if you replace1with a potential side-effect likesin 2.3(sinis pure, but the compiler can’t prove it), then the compiler can’t safely reduce the expression, thus hitting value restriction as withgenerate3.