I have this question about sum types in Haskell.
I'd like to create a sum type which is comprised of two or more other types, and each of the types may contain multiple fields. A trivial example would be like this:
data T3 = T1 { a :: Int, b :: Float} | T2 { x :: Char } deriving (Show)
In my understanding, T1
and T2
are data constructors which use record syntax. It seems that the definition of T3
will grow as the number of fields in T1
or T2
increases. My question is that how to practically handle these sum type constructors if the number of fields are large? Or, is it a good idea to mix sum type with record syntax?
I don't quite understand what concerns you have, but to answer the question in the last line: no, it is rather not a good idea to mix sum types with record syntax. Records in general remain a bit of a weak spot of the Haskell language; they don't handle scoping very well at all. It's usually fine as long as you just have some seperate types with different record labels, but as soon as sum types or name clashes come in it gets rather nasty.
In particular, Haskell permits you to use a record field accessor of the T1
constructor for any value of type T3
– print $ a (T2 'x')
will compile without warnings, but give a rather hard to foresee error at runtime.
In your example, it fortunately looks like you can easily avoid that kind of trouble:
data T3 = T3_1 T1 | T3_2 T2
deriving (Show)
data T1 = T1 { a :: Int
, b :: Float}
deriving (Show)
data T2 = T2 { x :: Char }
deriving (Show)
Now, any deconstruction you could write will be properly typechecked to make sense.
And such a structure of meaningful, small specialised sub-types† is generally better to handle than a single monolithic type, especially if you have many functions that really deal only with part of the data structure.
The flip side is that it gets quadratically tedious to unwrap the layers of constructors, but that's fortunately a solved problem now: lens libraries allow you to compose accessor/modifiers very neatly.
Speaking of solved problems: Nikita Volkov has come up with a really nice concept for entirely replacing the problem-ridden record syntax.
†Um... actually these aren't subtypes in any proper sense of the word, but you get what I mean.