2014-09-29 17 views
6

Spesso ho una funzione con più parametri dello stesso tipo e talvolta li uso nell'ordine sbagliato. Come semplice esempioI tipi di phantom F # in pratica

let combinePath (path : string) (fileName : string) = ... 

Mi sembra che i tipi fantasma sarebbe un buon modo per catturare alcun up mix. Ma non capisco come applicare l'esempio nell'unico F# phantom types question.

Come implementare i tipi di phantom in questo esempio? Come chiamerei combinePath? O mi manca una soluzione più semplice al problema?

risposta

12

Penso che il modo più semplice è quello di utilizzare i sindacati discriminati:

type Path = Path of string 
type Fname = Fname of string 
let combinePath (Path(p)) (Fname(file)) = System.IO.Path.Combine(p, file) 

Si può chiamare in questo modo

combinePath (Path(@"C:\temp")) (Fname("temp.txt")) 
+5

in quanto tali sono un caso a valle, si può anche fare 'lasciare combinePath (percorso (P)) (Fname (f)) = ...', alla fine -risultato sarà lo stesso :) –

+0

Sì. Sarà più semplice. Post aggiornato, grazie! – Petr

+0

Ciò significherebbe dichiarare un tipo per ogni tipo di parametro. Immagino che stavo pensando che potrebbe essere una sorta di unità di misura, stringa stringa . Sebbene abbia ancora bisogno di tipi per Path e FileName anche in questo modo, alla fine è tutto uguale ... a mio avviso, penso. –

7

Sono d'accordo con introito di Petr, ma per completezza, si noti che solo tu puoi usa i tipi di fantasma quando hai un tipo generico per usarli, quindi non puoi fare nulla con semplici input string. Invece, si potrebbe fare qualcosa di simile:

type safeString<'a> = { value : string } 

type Path = class end 
type FileName = class end 

let combinePath (path:safeString<Path>) (filename:safeString<FileName>) = ... 

let myPath : safeString<Path> = { value = "C:\\SomeDir\\" } 
let myFile : safeString<FileName> = { value = "MyDocument.txt" } 

// works 
let combined = combinePath myPath myFile 

// compile-time failure 
let combined' = combinePath myFile myPath 
+0

Chiaramente l'unione discriminata è il modo migliore per farlo. I tipi di fantasma sembrano ridondanti per F #. Immagino sia per questo che non c'è molta copertura di esso. –

+0

@FsharpPete - Non penso che sia giusto; in questo particolare scenario le DU possono essere migliori, ma ci sono certamente scenari in cui i tipi di fantasma sono utili (e non penso che F # sia notevolmente diverso dalla maggior parte degli altri linguaggi in termini di quando usare una tecnica o l'altra). – kvb

+0

Sì, lo vedo ora. Con l'approccio dei tipi di fantasmi è possibile specificare il tipo di fantasma dall'esterno del modulo/pacchetto, non con il sindacato discriminato. –

Problemi correlati