Implementing `MonadBaseControl IO` for application type

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

Implementing `MonadBaseControl IO` for application type

Magnus Therning
Hi,

I'm getting stuck on implementing `MonadBaseControl IO` for my application context type. What I have so far (in a minimized example) is

```
data Env = Env {envBalance :: !(TVar Int)}

newtype AppM a = AppM { unAppM :: ReaderT Env IO a }
  deriving (Functor, Applicative, Monad, MonadIO, MonadReader Env)

instance MonadBase IO AppM where
  liftBase = liftIO

instance MonadBaseControl IO AppM where
  type StM AppM a = a
  liftBaseWith f = undefined
  restoreM = return
```

I'm so utterly stuck on the definition of `liftBaseWith`... but I'm not 100% sure on the other bits either, though it "feels right".

Any tips on how I should go about it?

/M

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Implementing `MonadBaseControl IO` for application type

Li-yao Xia-2
Hi Magnus,

You can use GeneralizedNewtypeDeriving:

     deriving (..., MonadBase IO, MonadBaseControl IO)

To do it by hand, since AppM is a newtype around ReaderT, use the fact
that is already is an instance of MonadBaseControl.

     liftBaseWith f = AppM (liftBaseWith (\run -> f (run . unAppM)))

To discover that implementation, you can start with the idea that
liftBaseWith should basically be the same as the one as for ReaderT,
using TypeApplications to make explicit the instance we want to use:

     liftBaseWith = liftBaseWith @IO @(ReaderT Env IO)

And then fix the type errors by inserting AppM and unAppM in the right
places, possibly after eta-expanding some things.

     liftBaseWith f = liftBaseWith @IO @(ReaderT Env IO) f
     liftBaseWith f = liftBaseWith @IO @(ReaderT Env IO) (\run -> f run)
     -- The type errors now point exactly to the two locations that need
changing.

The rest of your implementation looks good.

Li-yao

On 2/2/19 6:28 AM, Magnus Therning wrote:

> Hi,
>
> I'm getting stuck on implementing `MonadBaseControl IO` for my
> application context type. What I have so far (in a minimized example) is
>
> ```
> data Env = Env {envBalance :: !(TVar Int)}
>
> newtype AppM a = AppM { unAppM :: ReaderT Env IO a }
>    deriving (Functor, Applicative, Monad, MonadIO, MonadReader Env)
>
> instance MonadBase IO AppM where
>    liftBase = liftIO
>
> instance MonadBaseControl IO AppM where
>    type StM AppM a = a
>    liftBaseWith f = undefined
>    restoreM = return
> ```
>
> I'm so utterly stuck on the definition of `liftBaseWith`... but I'm not
> 100% sure on the other bits either, though it "feels right".
>
> Any tips on how I should go about it?
>
> /M
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
>
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Implementing `MonadBaseControl IO` for application type

Magnus Therning

Li-yao Xia <[hidden email]> writes:

> Hi Magnus,
>
> You can use GeneralizedNewtypeDeriving:
>
>     deriving (..., MonadBase IO, MonadBaseControl IO)

I did start out with that, but got this from the compiler:

    Main.hs    18  26 error           error:
        • The type family application ‘StM (ReaderT Env IO) a’
            is no smaller than the instance head ‘StM AppM a’
          (Use UndecidableInstances to permit this)
        • In the instance declaration for ‘MonadBaseControl IO
        AppM’

Adding `UndecidableInstances` is something I'm not quite
comfortable with,
since I don't understand what it means.

> To do it by hand, since AppM is a newtype around ReaderT, use
> the fact that is
> already is an instance of MonadBaseControl.
>
>     liftBaseWith f = AppM (liftBaseWith (\run -> f (run .
>     unAppM)))
>
> To discover that implementation, you can start with the idea
> that liftBaseWith
> should basically be the same as the one as for ReaderT, using
> TypeApplications
> to make explicit the instance we want to use:
>
>     liftBaseWith = liftBaseWith @IO @(ReaderT Env IO)
>
> And then fix the type errors by inserting AppM and unAppM in the
> right places,
> possibly after eta-expanding some things.
>
>     liftBaseWith f = liftBaseWith @IO @(ReaderT Env IO) f
>     liftBaseWith f = liftBaseWith @IO @(ReaderT Env IO) (\run ->
>     f run)
>     -- The type errors now point exactly to the two locations
>     that need
> changing.
Thanks. That's excellent advise, I'll need to add that extension,
`TypeApplications`, to my toolbox right away.

> The rest of your implementation looks good.

Thanks for your help!

/M

--
Magnus Therning              OpenPGP: 0x927912051716CE39
email: [hidden email]
twitter: magthe              http://magnus.therning.org/

Reality is that which, when you stop believing in it, doesn't go
away.
     — Philip K. Dick

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (847 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Implementing `MonadBaseControl IO` for application type

Jack Kelly
Magnus Therning <[hidden email]> writes:

> Li-yao Xia <[hidden email]> writes:
>
> Adding `UndecidableInstances` is something I'm not quite comfortable
> with,
> since I don't understand what it means.

UndecideableInstances is not too bad, because the default heuristic in
Haskell2010 is very conservative.

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-UndecidableInstances

-- Jack
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.