In this post, we are going to create a Converter class who converts values to strings. The conversion rules are speciﬁed by passing the name of a culture to the class’ constructor. The culture name can contain just the language (as ISO 639-1 alpha-2 code, e. g. “en”) or the language and region (as ISO 3166 code, e. g. “US”) combined with hyphen, e. g. “en-US”. An empty culture name “” specifies the invariant culture, which falls back to “en”.
The class has only one conversion method ToString, who is generic. It takes a single parameter, which is the value to be converted. The parameter’s type is inferred to have a member constraint, who restricts the type (at compile time) to have an instance member with the signature
ToString: IFormatProvider -> string. The parameter’s member is invoked with a member constraint invocation expression.
type Converter(cultureName:string) =
/// The culture used by this converter.
member val Culture = CultureInfo.GetCultureInfo cultureName
/// Converts value to a string, based on the specified culture.
member inline self.ToString value =
(^T: (member ToString: IFormatProvider -> string)
let germanConverter = Converter "de"
let nrString = germanConverter.ToString 1234.643 // "1234,643"
let dtString = germanConverter.ToString <|
DateTime(2003, 11, 25, 17, 38, 47) // "25.11.2003 17:38:47"
Edit (Oct 15, 2012)
The converter's culture is now exposed via a public property, based on F# 3.0 auto property syntax. (The Culture's value is evaluated only once, during class construction time.) Previously, the culture was a private field, and the example could not compile in a regular source file, due to access rule violation. Strangely, it did compile in a scripting file; this is an example where the scripting compiler (wrongly) does not behave in the exact same way as the regular compiler.
This is a blog post in the “Brief tip” category. It is meant as a starting point for further investigation, not as a complete copy/paste solution to a specific concern you may have.