advice: instantiating/duplicating modules

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

advice: instantiating/duplicating modules

Nicolas Frisby
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. The class is called MonadRW and the transformer is
called RWT.

I find myself wishing I could import the same module twice, but
instead of having two names for the same entity, I want the
definitions proper of the module to be duplicated: I want two separate
MonadRW classes and two separate RWT transformers. Since the module
integrates the MonadRW and RWT transformer with the mtl, I would then
only need to lift the instances of the instantiated MonadRW classes
through the other RWTs.

I'm rather unfamiliar with Template Haskell, but it sounds like it
might fit the bill. Although, if I recall correctly, instances and
type declarations splicing are yet to be implemented in GHC?

Does anyone have any advice how to do this? I'm envisioning some
preprocessing. I'd like to know if someone has developed a tool for
this already or if this path has been attempted.

Thanks for your time,
Nick

PS - If this doesn't work out, I'm aware that I could use type-indexed
products and coproducts to pull it off, but I think that would
drastically reduce the number of  people who could understand/maintain
the code without having to learn such cool stuff.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: advice: instantiating/duplicating modules

Bulat Ziganshin-2
Hello Nicolas,

Friday, June 29, 2007, 9:07:38 PM, you wrote:

> I'm rather unfamiliar with Template Haskell, but it sounds like it
> might fit the bill. Although, if I recall correctly, instances and
> type declarations splicing are yet to be implemented in GHC?

instances - definitely not. i've used TH to generate Show instances

http://www.haskell.org/bz/th3.htm
http://www.haskell.org/bz/thdoc.htm

--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: advice: instantiating/duplicating modules

Arie Peterson
In reply to this post by Nicolas Frisby
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. The class is called MonadRW and the transformer is
| called RWT.
|
| I find myself wishing I could import the same module twice, but
| instead of having two names for the same entity, I want the
| definitions proper of the module to be duplicated: I want two separate
| MonadRW classes and two separate RWT transformers. Since the module
| integrates the MonadRW and RWT transformer with the mtl, I would then
| only need to lift the instances of the instantiated MonadRW classes
| through the other RWTs.
|
| I'm rather unfamiliar with Template Haskell, but it sounds like it
| might fit the bill. Although, if I recall correctly, instances and
| type declarations splicing are yet to be implemented in GHC?
|
| Does anyone have any advice how to do this? I'm envisioning some
| preprocessing. I'd like to know if someone has developed a tool for
| this already or if this path has been attempted.

Sounds familiar :-).

I wrote some TH code to get "named" versions of the StateT monad
transformer. Example usage:

> {-# OPTIONS_GHC -fth #-}
> module Test where
>
> import NamedStateT
>
> data Settings = ...
>
> $(namedStateT "Settings" $ Just $ ConT ''Settings)
>
> q :: (MonadSettings m,MonadIO m) => m ()
> q = do
>   settings <- getSettings
>   liftIO $ print settings
Notes:

- The second argument to namedStateT is the type of the state. |Nothing|
keeps it parameterised, like |StateT| itself.

- The big comment shows the code that would be generated by a typical
splicing, although the code may have been updated at some point without
changing the example accordingly.

- Not all instances and helper functions from Control.Monad.State are in
there; |modify| seems to be missing, for instance. If you need any, I can
add them (or you can do it yourself).

- I just saw I also have a NamedReaderT module, but it has never been
used, so it may not work. Yell if you think you can use it.


Kind regards,

Arie

--

Familiarity with the Haskell language is assumed, but no prior experience
with warm, fuzzy things is required.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

NamedStateT.hs (10K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: advice: instantiating/duplicating modules

Dave Bayer
In reply to this post by Nicolas Frisby
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.)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: advice: instantiating/duplicating modules

Arie Peterson
Dave Bayer wrote:

> 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.)

Yeah, a class/phantom type approach now seems more natural.

At the time, I had just learned about Template Haskell, and this problem
seemed like a nice nail :-). The code works for me, so I never bothered to
rewrite it.


Greetings,

Arie

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe