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