2017-07-28 5 views
4

Je suis novice en F # et j'essaie de trouver quelque chose pour comprendre la langue.F # Types et signatures de fonction

Je dois deux types presque identiques (Coordinate et Vector). En raison de ce type inférence ne peut pas fonctionner correctement et j'ai du mal à spécifier le type correct sur chaque fonction.

Il undestand en quelque sorte c'est un vecteur ici:

type Coordinate = {X:int; Y:int} 
type Vector = {X:int; Y:int} 

let calculateVector (origin:Coordinate) (destination:Coordinate) = { X=destination.X-origin.X; Y= destination.Y-origin.Y;} 

Et ici quand je veux un type de retour de coordonnées, je ne peux pas trouver comment spécifier le retour pour cette fonction:

let calculateNextCoordinate (coordinate:Coordinate) direction = 
    match direction with 
    | "N" -> { X=coordinate.X; Y=coordinate.Y-1 } 
    | "NE" -> { X=coordinate.X+1; Y=coordinate.Y-1 } 
    | "E" -> { X=coordinate.X+1; Y=coordinate.Y } 
    | "SE" -> { X=coordinate.X+1; Y=coordinate.Y+1 } 
    | "S" -> { X=coordinate.X; Y=coordinate.Y+1 } 
    | "SW" -> { X=coordinate.X-1; Y=coordinate.Y+1 } 
    | "W" -> { X=coordinate.X-1; Y=coordinate.Y } 
    | "NW" -> { X=coordinate.X-1; Y=coordinate.Y-1 } 
    | _ -> coordinate 

J'ai cette erreur sur le cas par défaut: Cette expression devait avoir «Vector», mais a ici le type «Coordinate»

i fatigué d'avoir un coup d'oeil sur ce site pour les signatures de fonction mais ne pouvait pas quelque chose pour mon problème: https://fsharpforfunandprofit.com/posts/function-signatures/

Questions:

Comment vous corriger cette erreur?

Est-ce parce que le type d'inférence prend par défaut le dernier type déclaré qui correspond aux propriétés (dans mon exemple Vector)? Bonus: Y a-t-il une meilleure façon de gérer ce genre de situation en F #?

Merci à l'avance

Répondre

6

Depuis les enregistrements sont construits en utilisant leurs noms de membres:

{ X = 2; Y = 3} 

vous avez créé un conflit de nom entre Vector et coordonnées. En F # le compilateur résout toujours à la dernière définition dans de tels cas et par conséquent, dans votre exemple, le compilateur interprétera l'enregistrement {X = ..., Y = ...} comme un vecteur.

Il ya un bon article sur F# records on fsharpforfunandprofit.com, qui explique comment gérer cela facilement, que je vous suggère de lire pour une bonne explication.

Mais en bref, vous pouvez préfixer soit membre de l'instance d'enregistrement avec le type d'enregistrement:

{ Coordinate.X = 2; Y = 3 } // Creates a Coordinate 
{ X = 2; Coordinate.Y = 3 } // Creates a Coordinate 

et

{ Vector.X = 2; Y = 3 } // creates a vector 
+0

Merci exactement ce que je recherchais, et les liens est vraiment bon . –