Record types with multiple constructors in haskell
haskell
Solution
When things start getting complicated, divide and conquer. Create complex entities by composing from simpler ones, not by ramming all the functionality into a single place. This has proven to be the optimal approach to programming in general, not just in Haskell.
Both your examples can benefit from separation. E.g.
data Block a = BinaryBlock (Binary a) | UnaryBlock (Unary a)
data Binary a = Binary {
...
}
data Unary = Unary {
...
}
Now you have `Binary` and `Unary` separated and you're able to write dedicated functions for each of them in isolation. Those functions will be much simpler and easier to reason about and maintain.
You'll also be able to benefit from putting those types in separate modules, which will resolve the field names collision. The final API for `Block` will be about very simple pattern matches and forwarding to specialised functions of `Binary` and `Unary`.
This approach is scalable. No matter how complex your entities or problems are you're always free to add another level of decomposition.
Problem
Very often when I write something using Haskell I need records with multiple constructors. E.g. I want to develop some kind of logic schemes modelling. I came up to such type: ``` data Block a = Binary { binOp :: a -> a -> a , opName :: String , in1 :: String , in2 :: String , out :: String } | Unary { unOp :: a -> a , opName :: String , in_ :: String , out :: String } ``` It describes two types of blocks: binary (like and, or etc.) and unary (like not). They contain core function, input and output signals. Another example: type to describe console commands. ``` data Command = Command { info :: CommandInfo , action :: Args -> Action () } | FileCommand { info :: CommandInfo , fileAction :: F.File -> Args -> Action () , permissions :: F.Permissions} ``` FileCommand needs additional field - required permissions and its action accept file as a first parameter. As I read and search topics, books etc. about Haskell, it seems that it is not common to use types with record syntax and many constructors simultaneously. So the question: is this "pattern" is not haskell-way and why? And if it is so, how to avoid it? P.S. Which from proposed layouts is better, or maybe there is more readable one? Because I can't find any examples and suggestions in other sources.