On 09-Jan-1999, S.D.Mechveliani <[EMAIL PROTECTED]> wrote:
> Here is a small awkwardness with naming.
> Example.
> Defining the operation of the set cardinality, we put naturally
> that it may return
> FiniteCard n, n >= 0 :: Integer
> InfiniteCard,
> UnknownCard
>
> But in this case, - as in many others, - there are several values
> in result which clearly cannot be returned by the operation.
> Thus, in the example, we can put
>
> class Set where card :: a -> Integer --has a sample argument
> ...
>
> and let card to return -1 for InfiniteCard, -2 for UnknownCard
>
> - and obtain the plainer program than by introducing the new data
> constructors.
> To make it even better, we have to name -1, -2 with the appropriate
> names and use them by names. Now, if we define
>
> infiniteCard = -1
>
> then the pattern matching suffers:
> case card a of infiniteCard -> g infiniteCard
> _ -> 2
> will yield wrong thing.
> Using the cpp preprocessor
>
> #define InfiniteCard -1
>
> would not do any good. Because cpp processes badly all the files
> where (') occurs - extra improvements for (') will spoil the
> plainness more than the constant naming helps it.
>
> I decided remain with case card a of -1 -> g infiniteCard
> _ -> 2
>
> But could anybody advise any better solution?
I advice just using a discriminated union -- this is exactly the
sort of situation they're designed for. Using a discriminated union
leads to clearer programs, IMHO, and reduces that danger of
accidentally forgetting one of the alternatives.
data Card = FiniteCard Natural
| InfiniteCard,
| UnknownCard
type Natural = Integer -- used for integers whose value should be >= 0
--
Fergus Henderson <[EMAIL PROTECTED]> | "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh> | but source code lives forever"
PGP: finger [EMAIL PROTECTED] | -- leaked Microsoft memo.