Passing values taking implicit parameters
Jan de Wit
Jan de Wit" <jwit@cs.uu.nl
Thu, 31 Jan 2002 10:09:11 +0100
From: "Johannes Waldmann":
[reply to Mike Gunter snipped]
> BEGIN wishlist:
>
> Now, can we please have defaults in data declarations? As in
>
> > data Foo = { host :: String, port = 9999 :: Int }
>
> Better still, can we construct default values,
> using values of other components, as in
>
> > data Tree = { top :: Item , left :: Tree, ..
> > , size = size (left self) + .. }
>
> This would require some means to refer to "the record under construction"
> (e. g. `self')
>
> The above example also shows that it should in fact be forbidden
> to override the `size' component.
>
> Perhaps it would be even better if we could define `size' later
> (not inside the data declaration).
>
> Note that some (most?) of the above is available for type *classes*,
> instead of types.
I think that what you want here are 'smart constructors', i.e. functions
that create a new value but also perform other initializations.
In the Tree example above, the code could look like:
> data Tree = Tree { item :: Item, ... }
> tree :: Item -> Tree -> Tree -> Tree
> tree item' left' right' = Tree
> { item = item'
> , left = left'
> , right = right'
> , size = size left' + size right' + 1
> , whatever more computations you need ... }
If you define Tree and the smart constructors in a separate module and then
only export the type Tree (*not* the real constructors!), the smart constrs
and suitable accessor functions, you can guarantee that the size is always
correct.
The Foo example could be turned into something like
> data Foo = Foo { host :: String, port :: Int }
> defaultFoo = Foo { port = 9999 }
> myFoo = defaultFoo { host = "haskell.org" }
> yourFoo = defaultFoo { host = "haskell.org", port = 80 }
HTH,
Jan de Wit