
Hi, I am new at Haskell and have some basic questions. Is there any way to do this more effectively? This causes the GHC compile error "Multiple declarations of Main.test": data A = A {test :: Int} data B = B {test :: Int} The Haskell 98 report in 4.2.1 under Labelled Fields says "A label cannot be shared by more than one type in scope. Field names share the top level namespace with ordinary variables and class methods and must not conflict with other top level names in scope." So then how should this be done? What if I want to do something like data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int} Also, could someone tell me why this doesn't compile in GHC: data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A} (Test2 line): Not in scope: type constructor or class 'A' Is there a way to qualify identical field names? What are some standard practices for dealing with this? Thanks, Jamin Ohmoto-Frederick -- View this message in context: http://www.nabble.com/basic-field-questions-tf3080392.html#a8558522 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Hallo,
On 1/24/07, jamin1001
So then how should this be done? What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
data Chair = Chair { chairPos :: Int, chairColor :: Int }
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
'A' is not a type, is a constructor for type 'Test'. -- -alex http://www.ventonegro.org/

jamin1001 wrote:
What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props or: data Chair = Chair Int Int data Table = Table Int Int class Furniture a where pos :: a -> Int color :: a -> Int instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c instance Furniture Table where ...
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
(Test2 line): Not in scope: type constructor or class 'A'
A is a data constructor, and not a type. Try: data Test2 = C { c :: Test }
Is there a way to qualify identical field names? What are some standard practices for dealing with this?
The record system is somewhat wartish, and there have been several proposals to remedy it. I'm not sure if any consensus has emerged yet. -k

Hallo,
On 1/24/07, Ketil Malde
jamin1001 wrote:
What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props
Do you mean: data Chair = Chair Properties data Table = Table Properties ? -- -alex http://www.ventonegro.org/

Thanks, that's much clearer now. Following this further, it seems that this could get monotonous/verbose if you have more than a handful of classes. I looked into "deriving" but it seems that is only useful for a set of builtin Haskell types (Eq, Ord, Show, etc.). Is Template Haskell the answer to automating some of this machinery? -Jamin Ketil Malde-2 wrote:
jamin1001 wrote:
What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props
or:
data Chair = Chair Int Int data Table = Table Int Int
class Furniture a where pos :: a -> Int color :: a -> Int
instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c
instance Furniture Table where ...
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
(Test2 line): Not in scope: type constructor or class 'A'
A is a data constructor, and not a type. Try:
data Test2 = C { c :: Test }
Is there a way to qualify identical field names? What are some standard practices for dealing with this?
The record system is somewhat wartish, and there have been several proposals to remedy it. I'm not sure if any consensus has emerged yet.
-k _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- View this message in context: http://www.nabble.com/basic-field-questions-tf3080392.html#a8561038 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

This is what I mean by "machinery": -- CASE 1 data Furniture = Furniture { pos, color :: Int } data Chair = Chair Furniture data Table = Table Furniture data Wooden = Wooden { grain :: Int } data WoodenFurniture = WoodenFurniture Wooden Furniture data WoodenTable = WoodenTable Wooden Table class GetFurniture a where getFurniture :: a -> Furniture instance GetFurniture Chair where getFurniture (Chair f) = f instance GetFurniture Table where getFurniture (Table f) = f instance GetFurniture WoodenFurniture where getFurniture (WoodenFurniture _ f) = f instance GetFurniture WoodenTable where getFurniture (WoodenTable _ (Table f)) = f class GetWooden a where getWooden :: a -> Wooden instance GetWooden WoodenFurniture where getWooden (WoodenFurniture w _) = w instance GetWooden WoodenTable where getWooden (WoodenTable w _) = w -- CASE 2 data Chair = Chair Int Int data Table = Table Int Int class Furniture a where pos :: a -> Int color :: a -> Int instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c instance Furniture Table where pos (Table x _) = x color (Table _ c) = c data WoodenFurniture = WoodenFurniture Int Int Int -- pos, color, grain data WoodenTable = WoodenTable Int Int Int -- pos, color, grain class Wooden a where grain :: a -> Int instance Wooden WoodenFurniture where grain (WoodenFurniture _ _ g) = g instance Furniture WoodenFurniture where pos (WoodenFurniture x _ _) = x color (WoodenFurniture _ c _) = c instance Wooden WoodenTable where grain (WoodenTable _ _ g) = g instance Furniture WoodenTable where pos (WoodenTable x _ _) = x color (WoodenTable _ c _) = c -- CASE 3 data FurnitureProp = FurnitureProp Int Int data Chair = Chair FurnitureProp data Table = Table FurnitureProp class Furniture a where pos :: a -> Int color :: a -> Int instance Furniture Chair where pos (Chair (FurnitureProp x _)) = x color (Chair (FurnitureProp _ c)) = c instance Furniture Table where pos (Table (FurnitureProp x _)) = x color (Table (FurnitureProp _ c)) = c data WoodenProp = WoodenProp Int data WoodenFurniture = WoodenFurniture FurnitureProp WoodenProp data WoodenTable = WoodenTable Table WoodenProp class Wooden a where grain :: a -> Int instance Wooden WoodenFurniture where grain (WoodenFurniture _ (WoodenProp g)) = g instance Furniture WoodenFurniture where pos (WoodenFurniture (FurnitureProp x _) _) = x color (WoodenFurniture (FurnitureProp _ c) _) = c instance Wooden WoodenTable where grain (WoodenTable _ (WoodenProp g)) = g instance Furniture WoodenTable where pos (WoodenTable (Table (FurnitureProp x _)) _) = x color (WoodenTable (Table (FurnitureProp _ c)) _) = c jamin1001 wrote:
Thanks, that's much clearer now.
Following this further, it seems that this could get monotonous/verbose if you have more than a handful of classes. I looked into "deriving" but it seems that is only useful for a set of builtin Haskell types (Eq, Ord, Show, etc.).
Is Template Haskell the answer to automating some of this machinery?
-Jamin
Ketil Malde-2 wrote:
jamin1001 wrote:
What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props
or:
data Chair = Chair Int Int data Table = Table Int Int
class Furniture a where pos :: a -> Int color :: a -> Int
instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c
instance Furniture Table where ...
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
(Test2 line): Not in scope: type constructor or class 'A'
A is a data constructor, and not a type. Try:
data Test2 = C { c :: Test }
Is there a way to qualify identical field names? What are some standard practices for dealing with this?
The record system is somewhat wartish, and there have been several proposals to remedy it. I'm not sure if any consensus has emerged yet.
-k _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- View this message in context: http://www.nabble.com/basic-field-questions-tf3080392.html#a8562642 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Ketil Malde
jamin1001 wrote:
What if I want to do something like data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int} data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props
or:
data Chair = Chair Int Int data Table = Table Int Int
class Furniture a where pos :: a -> Int color :: a -> Int
instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c
I'm not sure I follow what's really wanted here. Whats wrong with this:
data Colour = Black | Brown deriving (Enum, Show) data Furniture = Table {colour:: Colour, weight:: Double, height:: Double} | Chair {colour:: Colour, weight:: Double, squishiness:: Double} deriving Show
and then... ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base-1.0 ... linking ... done. Prelude> :l /tmp/foo.lhs Compiling Foo ( /tmp/foo.lhs, interpreted ) Ok, modules loaded: Foo. *Foo> colour $ Table {colour = Black, weight=1, height= 2} Black *Foo> colour $ Chair {colour = Brown, weight = 1, squishiness=100} Brown *Foo> The requirement is that all the "colour" fields have the same type.
The record system is somewhat wartish,
Sure, but it's not obvious to me that we're looking at one of the warts here, unless the problem is that my "Furniture" above isn't extensible in the appropriate sense or someone wants the different coulour fields to have different types (confusing, surely?). -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk

Well, it seems this approach doesn't allow you to group some fields together like "colour" and "weight", but instead you need to relist them piecemeal for each new data constructor. Also, you get a run-time error (rather than compile-time) if you happen to reference a field that didn't happen to exist in another data constructor, say like: sq = squishiness $ Table {colour = Black, weight=1, height= 2} main = putStr $ show sq main: No match in record selector Main.squishiness -Jamin Jon Fairbairn wrote:
Ketil Malde
writes: jamin1001 wrote:
What if I want to do something like data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int} data Properties = Props { pos, color :: Int } data Chair = Chair Props data Table = Table Props
or:
data Chair = Chair Int Int data Table = Table Int Int
class Furniture a where pos :: a -> Int color :: a -> Int
instance Furniture Chair where pos (Chair x _) = x color (Chair _ c) = c
I'm not sure I follow what's really wanted here. Whats wrong with this:
data Colour = Black | Brown deriving (Enum, Show) data Furniture = Table {colour:: Colour, weight:: Double, height:: Double} | Chair {colour:: Colour, weight:: Double, squishiness:: Double} deriving Show
and then...
___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help.
Loading package base-1.0 ... linking ... done. Prelude> :l /tmp/foo.lhs Compiling Foo ( /tmp/foo.lhs, interpreted ) Ok, modules loaded: Foo. *Foo> colour $ Table {colour = Black, weight=1, height= 2} Black *Foo> colour $ Chair {colour = Brown, weight = 1, squishiness=100} Brown *Foo>
The requirement is that all the "colour" fields have the same type.
The record system is somewhat wartish,
Sure, but it's not obvious to me that we're looking at one of the warts here, unless the problem is that my "Furniture" above isn't extensible in the appropriate sense or someone wants the different coulour fields to have different types (confusing, surely?).
-- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- View this message in context: http://www.nabble.com/basic-field-questions-tf3080392.html#a8599440 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Hi
sq = squishiness $ Table {colour = Black, weight=1, height= 2} main = putStr $ show sq
squishiness is just translated to: squishiness :: Furniture -> Double squishiness (Chair _ _ x) = x squishiness _ = error "doh"
main: No match in record selector Main.squishiness
Hence this is a pattern match error (runtime), not a type error (compile time). There are people working on extending the types to catch this kind of thing, and also people working on static checkers to catch patter match errors [1] and people working on annotations to get this kind of thing [2]. It's not a solved problem yet, but certainly I have a demo checker that would have spotted this easily. Thanks Neil [1] http://www-users.cs.york.ac.uk/~ndm/projects/catch.php [2] http://www.cl.cam.ac.uk/~nx200/research/escH-hw.ps

jamin1001 wrote:
Hi, I am new at Haskell and have some basic questions. So then how should this be done? What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
Unfortunately you have to think up different names for all constructors and field names that are declared anywhere in the same module. A possible methodical way to do this is to prefix all names by the type name (with first letter lowercase of course) eg: data Chair = Chair {chair_pos:: Int, chair_color :: Int} data Table = Table {table_pos:: Int, table_color :: Int} The reason is that when you declare a fieldname this also introduces a top level function with the same name which returns the relevant component of the record ie in the above the following top level functions are generated by the compiler: chair_pos :: Char -> Int chair_color :: Chair -> Int table_pos :: Table -> Int table_color :: Table -> Int
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
(Test2 line): Not in scope: type constructor or class 'A'
(A) is a data constructor whereas you need a type here, so it should be: data Test2 = C {c :: Test} Brian. -- http://www.metamilk.com

There is no good solution to your problem. But one way to have both the type A and the type B as you define them is to put them in separate modules and then use qualified names for the `test' function. -- Lennart On Jan 24, 2007, at 06:12 , jamin1001 wrote:
Hi, I am new at Haskell and have some basic questions.
Is there any way to do this more effectively? This causes the GHC compile error "Multiple declarations of Main.test":
data A = A {test :: Int} data B = B {test :: Int}
The Haskell 98 report in 4.2.1 under Labelled Fields says "A label cannot be shared by more than one type in scope. Field names share the top level namespace with ordinary variables and class methods and must not conflict with other top level names in scope."
So then how should this be done? What if I want to do something like
data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int}
Also, could someone tell me why this doesn't compile in GHC:
data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A}
(Test2 line): Not in scope: type constructor or class 'A'
Is there a way to qualify identical field names? What are some standard practices for dealing with this?
Thanks,
Jamin Ohmoto-Frederick -- View this message in context: http://www.nabble.com/basic-field- questions-tf3080392.html#a8558522 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Alex Queiroz
-
Brian Hulley
-
jamin1001
-
Jón Fairbairn
-
Ketil Malde
-
Lennart Augustsson
-
Neil Mitchell