Haskell Namespace Pollution Prevention

I use many different entries in the program, and some of them use the same field names, for example.

data Customer = Customer { ..., foo :: Int, ... } data Product = Product { ..., foo :: Int, ... } 

Now that the access function "foo" is defined twice, I get the error "Multiple declarations". One way to avoid this is to use various modules that are fully imported, or simply rename the fields (which I don't want to do).

What is the officially proposed way to handle this in Haskell?

+50
types namespaces haskell records
Nov 23 '10 at 20:21
source share
4 answers

This is a very hairy problem. There are several suggestions for fixing the recording system. For a related note, see TDNR and related cafe discussion ,

Using the currently available language features, I believe that the best option is to define two types in two different modules and perform qualified import. In addition, if you want, you can implement some type class machines.

At Customer.hs

 module Customer where data Customer = Customer { ..., foo :: Int, ... } 

In Product.hs

 module Product where data Product = Product { ..., foo :: Int, ... } 

When using them in Third.hs

 module Third where import qualified Customer as C import qualified Product as P .. C.foo .. .. P.foo .. 

However, I believe that it will not be too late before you encounter the problem of recursively dependent modules .

+22
Nov 23 '10 at 23:14
source share

(FYI, this question is almost certainly a duplicate)

Solutions:

1) Field prefix with a tag indicating the type (extremely common)

 data Customer = Customer {..., cFoo :: Int, ...} 

2) Use type classes (less common, people complaining about prefixes like cFoo are inconvenient, but obviously not so bad that they will write a class and instance or use TH to do the same).

 class getFoo a where foo :: a -> Int instance getFoo Customer where foo = cFoo 

3) Use the best field names. If the fields are really different (this is not always the case, my computer has an age, like my employee), then this is the best solution.

+12
Nov 23 '10 at 21:08
source share

See also Has package: http://chrisdone.com/posts/duck-typing-in-haskell

And if you really need advanced entries, you can always use HList. But I would not recommend this until you are really familiar and comfortable with the average advanced Haskell, and even then I would check three times that you need it.

Haskelldb has a slightly lighter version: http://hackage.haskell.org/packages/archive/haskelldb/2.1.0/doc/html/Database-HaskellDB-HDBRec.html

And here is another version of expandable entries as part of the grapfruit frp library: http://hackage.haskell.org/package/grapefruit-records

Again, for your purposes, I would bite a bullet and simply rename the fields. But these links show that when you really need the full power of expandable records, there are ways to do this, even if none of them are as enjoyable as a well-thought out language extension.

+7
Nov 24 '10 at 7:41
source share

There is an extension of the language DuplicateRecordFields , which allows you to duplicate the functions of the field and displays its type as an annotation.

Here is a small example ( haskell-stack script):

 #!/usr/bin/env stack -- stack runghc --resolver lts-8.20 --install-ghc {-# LANGUAGE DuplicateRecordFields #-} newtype Foo = Foo { baz :: String } newtype Bar = Bar { baz :: String } foo = Foo { baz = "foo text" } bar = Bar { baz = "bar text" } main = do putStrLn $ "Foo: " ++ baz (foo :: Foo) -- Foo: foo text putStrLn $ "Bar: " ++ baz (bar :: Bar) -- Bar: bar text 
+2
Jun 24 '17 at 12:28
source share



All Articles