Following a minimal observation example (it struck me):
type Vector = V of float*float // complete unfolding of type is OK let projX (V (a,_)) = a // also works let projX' x = match x with | V (a, _) -> a // BUT: // partial unfolding is not Ok let projX'' (V x) = fst x // consequently also doesn't work let projX''' x = match x with | V y -> fst y
What is the reason for the impossibility of matching with a partially deconstructed type?
Some partial deconstructs look fine:
// Works let f (x,y) = fst y
EDIT: Okay, now I understand the “technical” reason for the described behavior (Thanks for your answers and comments). However, I think the language is wise, this behavior seems a bit “unnatural” compared to the rest of the language:
"Algebraically," it seems strange to me to distinguish between type "t" and type "(t)". Brackets (in this context) are used to provide priority, for example, in "(t * s) * r" vs "t * (s * r)". Also fsi answers accordingly if I send
type Vector = (int * int)
or
type Vector = int * int
in fsi, the answer is always
type Vector = int * int
Given these observations, it is concluded that "int * int" and "(int * int)" mean exactly the same types and, therefore, all occurrences of one can be replaced with any piece of code by another (ref.) ... which, as we have seen, is wrong.
Further, it seems important that to explain the behavior at hand, we had to resort to talking about “what some kind of code looks like after compilation”, and not about the semantic properties of the language, which indicates that there are some “tensions” between the semantics of the language and what the compiler does.