[Haskell-cafe] advice: instantiating/duplicating modules
Dave Bayer
bayer at cpw.math.columbia.edu
Fri Jun 29 21:29:20 EDT 2007
On Jun 29, 2007, at 10:07 AM, Nicolas Frisby wrote:
> I wrote a combination reader/writer monad (a la the RWS monad in the
> mtl) and I find myself wanting to use multiple instances of it in the
> same stack of transformers. The functional dependencies prevent this
> from working out.
I found myself in a situation implementing two very similar
algorithms where I had to really puzzle out how to get functional
dependencies to work, and I ended up writing a class (I abridge):
> class (Num b, Real c) => Elem a b c | a -> b, a -> c where
> qr :: a -> b -> b -> QR c
and then declaring instances like
> data Rlist a = Rlist
> instance Integral a => Elem (Rlist a) a (Ratio a) where
> qr w x y = Yes (x % y) False
When I wanted this version of qr, I'd call "qr Rlist". Rlist is a
dummy class parameter to get the functional dependencies to work, it
does nothing besides select a version of my code. I couldn't get the
functional dependencies to work out any other way, so I accepted this.
Later, I realized that Haskell had named records, and I went back and
rewrote stuff as follows:
> data (Num b, Real c) => Elem b c = Elem {
> qr :: b -> b -> Rem c }
>
> rlist :: Integral a => Elem a (Ratio a)
> rlist = Elem {
> qr = (\x y -> Just (x % y, False)) }
Now all I had to do was change the case from "qr Rlist" to "qr rlist"
and the rest of my code worked exactly as before. (I love how often
this sort of thing happens in Haskell.) I went from thinking that
passing around a bunch of functions was kludgey, to thinking that a
beginner like me using multi-parameter type classes unnecessarily was
obfuscation. In any case, it didn't matter what I thought, the code
either way was virtually identical.
I've since done some experiments with Template Haskell, and I see
that Arie Peterson has suggested how you could proceed. However, are
you sure that you can't find a way to get this to work in vanilla
Haskell without extensions? Or, for that matter, are you sure there
isn't a way to get functional dependencies to work? (I felt pretty
dumb for a little while before I found one for my problem, although
as usual the issues are clear in hindsight.)
More information about the Haskell-Cafe
mailing list