
On Monday 01 November 2004 21:51, Jon Fairbairn wrote:
On 2004-11-01 at 12:30PST "Brian Beckman" wrote:
Most interesting discussion -- in reading it, I realized that I had a 'hidden agenda' in asking my question (hidden even from myself), and that is: can I put interesting functionality, like precondition checks & data validation, in data constructors?
No, though one could make a case that you should be able to.
And there are (experimental) languages in which you can, see e.g. Cayenne or Epigram. 'Dependent Types' is the keyword here.
I suspect not, and that's why I tend to write something like the following:
data Shape = Circle Float
| Square Float
deriving (Eq, Show)
circle :: Float -> Shape circle x = if (x <= 0) then error "Bad radius!" else Circle x
That's fine,
Yup.
but I don't know how to prevent users from calling "Circle" directly
Put the data declaration in a module, export the type, but
not the constructor you want to hide:
module Shape (Shape(Square), circle) where
Since we were talking about 'what can one do with a constructor as compared with a function', it should be mentioned that this also has a disadvantage: you loose pattern matching outside the module. I.e. no longer can say ... case x of Circle radius -> ... Square edge -> ... BTW, would it be possible (in principle) to allow constructor export 'read-only', so matching against a constructor is allowed but not constructing a value? Ben