<div dir="ltr">This seems like a case where you only really need a record, not a typeclass.<br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 8, 2015 at 2:47 PM Dimitri DeFigueiredo <<a href="mailto:defigueiredo@ucdavis.edu">defigueiredo@ucdavis.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello!<br>
<br>
I am trying to tie together a group of functions that turn an unreliable<br>
remote network call into a reliable one. For each different network<br>
request I make, a specific group of these functions should always work<br>
together, but their type signatures are quite different. My first<br>
thought was to put them all in a typeclass:<br>
<br>
import Control.Monad<br>
<br>
class Reliable1 m req attempt ack failure result where<br>
     getRequests1 :: Monad m =>               m [req]<br>
     mkAttempt1   :: Monad m => req        -> m (Maybe attempt)<br>
     action1      :: Monad m => attempt    -> m (Maybe ack)<br>
     getAcks1     :: Monad m => [attempt]  -> m [ack]<br>
     mkResult1    :: Monad m => req -> ack -> m (Either failure result)<br>
     run1         :: Monad m => req        -> m result<br>
<br>
That doesn't work because not all functions use all parameters. For<br>
example, getAcks1 has no idea of what the final 'result' type parameter<br>
is. This lead me to my second attempt. Defining a 'service' type with<br>
the sole purpose of tying them all together. Here's my current attempt:<br>
<br>
{-# LANGUAGE MultiParamTypeClasses #-}<br>
<br>
import Control.Monad<br>
<br>
class Reliable m service where<br>
     getReqs     :: Monad m => service ->               m [req]<br>
     mkAttempt   :: Monad m => service -> req        -> m (Maybe attempt)<br>
     action      :: Monad m => service -> attempt    -> m (Maybe ack)<br>
     getAcks     :: Monad m => service -> [attempt]  -> m [ack]<br>
     mkResult    :: Monad m => service -> req -> ack -> m (Either<br>
failure result)<br>
     run         :: Monad m => service -> req        -> m result<br>
<br>
data RemoteCall = RemoteCall<br>
<br>
instance Reliable IO RemoteCall where<br>
     getReqs     = undefined<br>
     mkAttempt   = undefined<br>
     action      = undefined<br>
     getAcks     = undefined<br>
     mkResult    = undefined<br>
     run         = undefined<br>
<br>
This works, but I have to explicitly pass the 'service' argument in<br>
every call.<br>
Can I avoid passing this parameter every time?<br>
Question, is there a better way to do this?<br>
I wanted to have a wrapper to make my remote calls reliable.<br>
<br>
Thanks,<br>
<br>
Dimitri<br>
<br>
<br>
<br>
_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners</a><br>
</blockquote></div>