# [Haskell-beginners] Exposing Ratio data constructor in prelude

Brent Yorgey byorgey at seas.upenn.edu
Mon Sep 29 12:28:47 EDT 2008

```On Mon, Sep 29, 2008 at 06:16:24PM +0200, Casey Rodarmor wrote:
> Hej hej!
>
> I was writing some code using Ratio, and even though I know it's
> tucked behind an abstraction barrier, I really wanted access to the
> Ratio data constructor ':%'. I wrote invertRatio like such:
>
> invertRatio r = denominator r % numerator
>
> But I really wanted to write it like this:
>
> invertRatio (n :% d) = d % n
>
> I understand that exposing ':%' causes problems, since it allows us
> not only to pick apart ratios, but to construct bad ones that would
> normally be caught when constructed with '%'. (Such as '1:%0'.)
>
> Is there any way to avoid this, while still letting the user benefit
> from the nice pattern matching syntax that exposing the data
> constructor allows?

Well, one way to do it would be to write your own destructor function, like so:

nd :: Ratio a -> (a,a)
nd r = (numerator r, denominator r)

Then you could use it with a pattern guard:

invertRatio r | (n,d) <- nd r = d % n

But that's still a bit more syntactically heavyweight than what you'd
really like.  The real answer to your question is views, as proposed
by Wadler in 1987 [1].  Views allow pattern matching to be abstracted
away from the actual representation of a type.  Unfortunately, GHC
6.8.3 does not include views... but GHC 6.10 will! [2] Using GHC 6.10
with the -XViewPatterns extension, you could rewrite invertRatio like
this:

invertRatio (nd -> (n,d)) = d % n

-Brent

1. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.3532