I promise not to make the Haskell struct mistake.
In a typical OO language, eg, Python, you'd do:
class Foo(object):
def __init__(self, bar):
self.bar = bar
foo = Foo("bar")
# prints 'bar'
print foo.bar
In Haskell: data Foo = Foo { bar :: String }
main = do
let foo = Foo "bar"
-- prints 'bar'
putStrLn (bar foo)
Here, you can see that Haskell generates an accessor 'bar' which is a top-level function. Which means that if you can't have two records with a 'bar' field in the same module. You can have a 'bar' field in a different module, but then you need to a qualified import (import qualified OtherModule as O) in order to work around the conflict (forcing you to type ugly O.bar every time you need the 'bar' accessor from OtherModule). So you end up putting prefixes everywhere, something which in my opinion is a design mistake.One advantage I'll admit is that in Haskell you have to actively watch out for ambiguities and refactor colliding types to import as qualified.
O.bar foo doesn't look that bad, does it? Sure. Except when you have nested data structures. And you very often have nested data structures. Not to mention that I'm not about to split my data definitions into 50 different modules when working with a database. You know, these pesky things things which so often have a field called "id"...
So instead of the language doing for you, you get to do "namespacing" yourself by prefixing your fields by an abbreviated version of your data type name.
However, you still run into the same namespacing issue we talked about, because at the end of the day, lenses are a bit of wonderful magic on top of the existing, crummy record system.
You'd create a Lens like so (with Control.Lens):
-- You're supposed to prefix by _ due to Template Haskell magic following, but it's still a plain record, namespacing issues and all
data Foo = Foo { _bar :: String }
-- TH magic making lenses for all fields
makeLenses ''Foo
Now you have a 'bar' lens: -- prints 'bar'
putStrLn (foo^.bar)
-- creates a copy of 'foo' with 'bar' set to 'barbar'
let foo' = foo & bar .~ "barbar"