I often have a function with multiple parameters of the same type, and sometimes use them in the wrong order. As a simple example
let combinePath (path : string) (fileName : string) = ...
It seems to me that phantom types would be a good way to catch any mix ups. But I don't understand how to apply the example in the only F# phantom types question.
How would I implement phantom types in this example? How would I call combinePath? Or am I missing a simpler solution to the problem?
I think the easiest way is to use discriminated unions:
type Path = Path of string
type Fname = Fname of string
let combinePath (Path(p)) (Fname(file)) = System.IO.Path.Combine(p, file)
You could call it this way
combinePath (Path(@"C:\temp")) (Fname("temp.txt"))
I agree with Petr's take, but for completeness, note that you can only use phantom types when you've got a generic type to use them with so you can't do anything with plain string
inputs. Instead, you could do something like this:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With