Typeclasses -- if does not satisfy

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

Typeclasses -- if does not satisfy

Dmitry Bogatov
Hello! I am working on package to generalize
common `runSomeThing` and `runSomethingT` functions.

It is very easy to generalize runStateT and runReaderT
like

        class Runnable a where
              type RunResult a
              run :: a -> RunResult a
        instance Runnable (StateT s m a) where
              --- Why ScopedTypeVariables do not work here?
              type RunResult (StateT s m a) = s -> m (a, s)
              run = runStateT
        --- ReaderT absolutely the same

But problem is that `State s a` is in fact `StateT s Identity a` and
I get type family conflicts.

In fact, it boils down to following:

   type family TestIdentity (m :: * -> *)
   type instance TestIdentity Identity = Int
   type instance TestIdentity m = () -- Anything but Identity.

In general, with all this TypeClass magic, I have a lot of ways that
something belong to some class, and no (aside OverlappingInstances)
to tell that it does NOT belong. I belive, there is reason to, but I do
not see it. Also, seems even TH does not helps here.

PS. Please, keep me in To:

--
Best regards, Dmitry Bogatov <[hidden email]>,
Free Software supporter, esperantisto and netiquette guardian.
        git://kaction.name/rc-files.git
        GPG: 54B7F00D
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Typeclasses -- if does not satisfy

Adam Vogt
Hi Dmitry,

It's pretty straightforward to use OverlappingInstances:

class Runnable a b where
      run :: a -> b

instance (r ~ (s -> (m (a,s)))) => Runnable (StateT s m a) r where
      run m = runStateT m

instance (r ~ (s -> (a,s))) => Runnable (StateT s Identity a) r where
      run m = runState m

Involving a type family doesn't simplify things, since you still need
two class instances to choose between runStateT and runState.


With TH you could avoid overlapping instances by looking at the names
in (reify ''Monad) to replace the type variable `m' with a particular
instance of Monad. In other words, with TH you can generate many many
instances that look like:

instance (r ~ (s -> (IO (a,s)))) => Runnable (StateT s IO a) r where
      run m = runStateT m

instance (r ~ (s -> (ReaderT t (a,s)))) => Runnable (StateT s (ReaderT
t) a) r where
      run m = runStateT m

And then users that define their own instances of Monad would have run
the same TH for Runnable to work. Is that the unpleasant scenario you
mean by "even TH does not helps here"?

Regards,
Adam

On Sat, May 24, 2014 at 10:53 AM, Dmitry Bogatov <[hidden email]> wrote:

> Hello! I am working on package to generalize
> common `runSomeThing` and `runSomethingT` functions.
>
> It is very easy to generalize runStateT and runReaderT
> like
>
>         class Runnable a where
>               type RunResult a
>               run :: a -> RunResult a
>         instance Runnable (StateT s m a) where
>               --- Why ScopedTypeVariables do not work here?
>               type RunResult (StateT s m a) = s -> m (a, s)
>               run = runStateT
>         --- ReaderT absolutely the same
>
> But problem is that `State s a` is in fact `StateT s Identity a` and
> I get type family conflicts.
>
> In fact, it boils down to following:
>
>    type family TestIdentity (m :: * -> *)
>    type instance TestIdentity Identity = Int
>    type instance TestIdentity m = () -- Anything but Identity.
>
> In general, with all this TypeClass magic, I have a lot of ways that
> something belong to some class, and no (aside OverlappingInstances)
> to tell that it does NOT belong. I belive, there is reason to, but I do
> not see it. Also, seems even TH does not helps here.
>
> PS. Please, keep me in To:
>
> --
> Best regards, Dmitry Bogatov <[hidden email]>,
> Free Software supporter, esperantisto and netiquette guardian.
>         git://kaction.name/rc-files.git
>         GPG: 54B7F00D
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Typeclasses -- if does not satisfy

Dmitry Bogatov
* adam vogt <[hidden email]> [2014-05-24 12:27:18-0400]

> Hi Dmitry,
>
> It's pretty straightforward to use OverlappingInstances:
>
> class Runnable a b where
>       run :: a -> b
>
> instance (r ~ (s -> (m (a,s)))) => Runnable (StateT s m a) r where
>       run m = runStateT m
>
> instance (r ~ (s -> (a,s))) => Runnable (StateT s Identity a) r where
>       run m = runState m
>
> Involving a type family doesn't simplify things, since you still need
> two class instances to choose between runStateT and runState.

So simple and so good. Thank you.

--
Best regards, Dmitry Bogatov <[hidden email]>,
Free Software supporter, esperantisto and netiquette guardian.
        git://kaction.name/rc-files.git
        GPG: 54B7F00D
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe