Y a-t-il quelque chose d'intrinsèquement différent dans la conception ou l'idéologie de F# qui en est la cause ?
Oui. F# utilise le typage nominal plutôt que structurel parce qu'il est plus simple et, par conséquent, plus facile à utiliser pour les simples mortels.
Considérez cet exemple F# :
let lengths (xss: _ [] []) = Array.map (fun xs -> xs.Length) xss
let lengths (xss: _ [] []) = xss |> Array.map (fun xs -> xs.Length)
La première ne compile pas car le type de l'élément xs
à l'intérieur de la fonction anonyme ne peut pas être déduite parce que F# ne peut pas exprimer le type "une classe avec une fonction anonyme". Length
membre".
En revanche, OCaml peut exprimer l'équivalent direct :
let lengths xss = Array.map (fun xs -> xs#length) xss
car OCaml peut exprimer ce type (il est écrit <length: 'a ..>
). Notez que cela nécessite une inférence de type plus puissante que celle dont disposent actuellement F# ou Haskell, par exemple, OCaml peut inférer des types de somme.
Cependant, cette fonctionnalité est connue pour être un problème d'utilisation. Par exemple, si vous faites une erreur ailleurs dans le code, le compilateur n'a pas encore déduit que le type de l'élément xs
était censé être un tableau, donc tout message d'erreur qu'il peut donner ne peut fournir que des informations comme "un type avec un membre Length" et non "un tableau". Avec un code à peine plus compliqué, cela devient rapidement incontrôlable car vous avez des types massifs avec de nombreux membres structurellement inférés qui ne sont pas tout à fait unifiés, ce qui conduit à des messages d'erreur incompréhensibles (de type C++/STL).