3 ms·
Also one thing that always gave me pause about Haskell was the record system, and the inability to have fields with the same name in the same module (especially
by tmhedberg 14y ago
Also one thing that always gave me pause about Haskell was the record system, and the inability to have fields with the same name in the same module (especially when the fields are generated from a database). Has there been any progress on that front?
There have been a zillion proposals, but as far as I know, not much actual consensus or implementation work.
Anecdotally, I've never run into a situation where this was anything more than a minor annoyance. I don't doubt that it can be a problem under the right set of circumstances, but I think the issue gets more attention than its magnitude truly merits. People theorize a lot about the difficulties it can hypothetically cause, but in practice, it seldom actually manifests itself.
- fusiongyro 14y agoMy experience has been the same. I think this is why the various proposals have mostly faltered; it's not a big enough pain point in practice.
- evmar 14y agoIn my experience it was a perpetual pain point. Do you namespace all your field names with a common prefix based on the outer type name? Or do you just get lucky and not have the names collide?
- hesselink 14y agoIn the past most people prefixed their field names with the type name. Nowadays, the most common thing is to put types in their own module, and use the module system to sort out any conflict. Qualified imports can add a prefix, but you can also import parts unqualified, or hide one problematic field.
- mifrai 14y agoWhile I prefer the module solution, it's not always possible when you have mutually recursive record definitions. Well, technically it is possible - but it's very unpleasant [1]. [1] http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#mutual-recursion http://www.haskell.org/ghc/docs/latest/html/users_guide/sepa...
- papsosouid 14y agoI've had quite the opposite experience. Every programmer I've convinced to try haskell has had problems with records. It is incredibly limiting when coming from any language that has objects or structs. Having to prepend every single name in every single record with the information that is already in that record's name is horribly ugly. I think there is no progress made because nobody can decide on a perfect solution, so all the good enough solutions sit and rot.
- tmhedberg 14y agoI suppose that, in my personal experience, I just haven't written a lot of Haskell code that used multiple similar record types in the same namespace. I don't have any evidence for this, but I feel like it's often a bit of a code smell when this problem crops up. It seems like it frequently happens when programmers used to OOP are trying to shoehorn an object oriented design into a language which is just fundamentally not object oriented. I'm not saying that that's the only situation in which this problem arises, nor that the complaint isn't a legitimate one, regardless. There is no question that the situation could be improved. And perhaps I've just gotten lucky so far and haven't come across a scenario in which this really causes difficulties. That said, there are always ways to work around the issue. I will make no claims of elegance here, but it's really not that much trouble. For one, you can define the different record types in separate modules, and then import them qualified. That's easy enough to do; it's just annoying to have to use multiple files. Alternatively, you can keep the ugly prefixes on the record field names, but then use a type class to elide them away everywhere you refer to them. This technique only works when the similarly-named fields have the same type in each record, unless you use fundeps or associated types to attach additional type information to your class. For example: {-# LANGUAGE TypeFamilies #-} data Foo = Foo {foo_field1 :: Char, foo_field2 :: String} data Bar = Bar {bar_field1 :: Int, bar_field2 :: String} class MyRecord a where type Field1Type a field1 :: a -> Field1Type a field2 :: a -> String instance MyRecord Foo where type Field1Type Foo = Char field1 = foo_field1 field2 = foo_field2 instance MyRecord Bar where type Field1Type Bar = Int field1 = bar_field1 field2 = bar_field2 You could even use Template Haskell to automatically generate the instances so you don't have to tediously type them out yourself, especially handy for records with a large number of fields. So I'm not claiming that there's no problem to be solved. I would be happy to see a real solution to this that doesn't require any workarounds. I just don't think it's a big enough issue to keep me from using a language which is, in nearly all other respects, awesome. :)