Discussion:
[Haskell-beginners] Exposing Ratio data constructor in prelude
Casey Rodarmor
2008-09-29 16:16:24 UTC
Permalink
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?

Kram,
Casey
Brent Yorgey
2008-09-29 16:28:47 UTC
Permalink
Post by Casey Rodarmor
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
invertRatio r = denominator r % numerator
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

Hope that answers your question!

-Brent


1. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.3532
2. http://www.haskell.org/ghc/dist/stable/docs/users_guide/syntax-extns.html#view-patterns
Post by Casey Rodarmor
Kram,
Casey
_______________________________________________
Beginners mailing list
http://www.haskell.org/mailman/listinfo/beginners
Loading...