A smart constructor is a constructor-like function that creates a value while checking properties the type system cannot guarantee. For a CSV value, it can ensure that the header size matches the number of columns and that all columns have equal lengths. section 7.2 section 7.5
A practical smart-constructor design separates safe construction from trusted use:
- Expose a checked function such as mkCsv that returns either an error message or a valid Csv value. section 7.2 section 7.2.2
- Use Either to make construction failures explicit instead of repeating invariant checks in every function that handles the value. section 7.2 section 7.5
- Provide an unsafeMkCsv alternative only when validity has already been established; invalid arguments cause it to crash. section 7.2.2
Checking a CSV value
mkCsv (Just ["First", "Second"]) [[int 1, int 2], [int 3, int 4]] produces a Right Csv value. Unequal column lengths produce Left "The columns do not have equal sizes", while a one-field header with two columns produces Left "Size of header row does not fit number of columns". section 7.2.2
ghci> :set -XOverloadedStrings
ghci> int x = IntValue x
ghci> mkCsv (Just ["First", "Second"]) [[int 1, int 2], [int 3, int 4]]
Right (Csv {csvHeader = Just ["First","Second"], csvColumns =
[[IntValue 1,IntValue 2],[IntValue 3,IntValue 4]]})
ghci> mkCsv (Just ["First", "Second"]) [[int 1, int 2], [int 3]]
Left "The columns do not have equal sizes"
ghci> mkCsv (Just ["First"]) [[int 1, int 2], [int 3, int 4]]
Left "Size of header row does not fit number of columns"
ghci> unsafeMkCsv Nothing [[int 1, int 2], [int 3]]
*** Exception: The columns do not have equal sizes
Interactive GHCi results compare successful checked construction, validation errors, and the unsafe constructor's exception. section 7.2.2


