
On 06/02/2011 07:58 PM, aditya siram wrote:
data KeyValuePair a b = KeyValuePair String String
'a' and 'b' are called phantom types and they are used to tag a datatype. Rather than explain what that means in some abstract way I'll just show you how I have used them:
I had the following simple program that retrieved values from and wrote to a dictionary data structure (like Oxford's or Webster's). Here are the types in Haskell: type Name = String type Definition = String type Dictionary = [(Name,Definition)]
The actual contents of the dictionary were stored in a SQLite database so I needed to read them into the "Dictionary" type whenever I started up the program.
And I had a number of functions that queried the "Dictionary" that required on a populated dictionary and I wanted to check *at compile time* that they would only be called on a populated dictionary. So I added the following two datatypes: data Populated = Populated data New = New
I then changed my "Dictionary" to take an extra argument that is never used just like your "KeyValuePair": type Dictionary a = [(Name,Definition)]
Now I could write a function that populated the dictionary: populateFromDatabase :: Dictionary New -> IO (Dictionary Populated)
and query functions: getDefinition :: Name -> Dictionary Populated -> Definition
Since "populateFromDatabase" is the only function that can create a "Dictionary Populated" the phantom type statically guarantees that "getDefinition" and any other function that expects a full dictionary can never be called before "populateFromDatabase".
The Haskell Wiki has a similar example [1] and Richard Jones has a nice article on they are used in Ocaml [2] .
hth, -deech
[1] http://www.haskell.org/haskellwiki/Phantom_type [2] http://camltastic.blogspot.com/2008/05/phantom-types.html
Thank you. The first reference link was especially helpful in explaining phantom types. One more question, out of curiosity: In your above example, you could change data Populated = Populated data New = New to simply data Populated data New correct? You might as well, right, since your constructors take no values, and you are just using them as phantom types? -- frigidcode.com theologia.indicium.us