
Wojtek NarczyĆski
Take a VAT Invoice as an example. You will have:
Invoice, InvoiceBuilder, InvoiceLineItem, InvoiceLineItemBuilder, InvoiceCustomer, InvoiceCustomerBuilder, InvoiceSummary, (no Builder, as this is calculated) (many, many more classes in a realistic system)
Now, where the rather complex validation belongs? Optional / mandatory requirements, lengths, ranges, regexps, control sums, field interdependencies, autocompletes, server sent notifications? Where to put all of this? To regular classes, to builder classes, or to both?
The current trend in OOP Web frameworks Model-View-Controller. In MVP, Invoice/InvoiceLineItem/InvoiceCustomer/InvoiceSummary/etc. are the Model: they should form a standalone 'simulation' of an Invoice, without concerning themselves with 'external' aspects. Validation, bootstrapping (builders), etc. live in the Controller layer. If the server notifications are informing the user about the behaviour of the Model, they're part of the View. If they facilitate interaction they're part of the Controller. There are many functional styles which suit Models: - The pseudo-imperative style of Applicative/Monad/Arrow/etc. - The 'interacting streams' style, eg. infinite [(Request, Response)] lists. - Functional Reactive Programming Since Controllers can't mutate Models in Haskell, they must do one of two things: - Influence some 'future' behaviour of the Model, eg. using FRP - Build a new Model from the given settings To me the latter choice looks similar to a parsing problem. You say that Haskell's "great" at parsing, which I think contradicts your statement that "in Haskell it is unusual to deal with data that is incomplete or otherwise erroneous". In Haskell we deal with incomplete data all the time using lazy evaluation. Erroneous data doesn't require Maybes all over our data: it just needs one big Maybe in the 'parsing' function; or, more likely, "Either [Error]" detailing the problems which were found. Views are straightforward: recurse over the data, use FRP, etc. Cheers, Chris