creating MonadBaseControl instance for newtype

不打扰是莪最后的温柔 提交于 2019-12-10 12:31:42

问题


Suppose I have simple newtype declaration

newtype Foo a = Foo { unFoo :: ReaderT Int IO a }

I want to make Foo instance of MonadBaseControl IO. It should be easy, since ReaderT Int IO is already an instance of MonadBaseControl IO. However, automatically deriving it using GeneralizedNewtypeDeriving doesn't work, because MonadBaseControl class has an associated type.

How can one write a MonadBaseControl IO instance for Foo? defaultLiftBaseWith and defaultRestoreM should be helpful, but it's a bit hard to decipher their types.


回答1:


Foo is neither a "base" monad, nor a monad transformer. defaultLiftBaseWith won't be helpful here, since you want the instance for Foo to be identical to the one for ReaderT Int IO.

First, use GND to get the boring instances:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Monad.Trans.Control
import Control.Monad.Base 
import Control.Monad.Reader 
import Control.Applicative

newtype Foo a = Foo { unFoo :: ReaderT Int IO a } 
  deriving (Monad, Applicative, Functor, MonadBase IO)

The instance for MonadBaseControl IO just removes the newtype, uses the functions from the ReaderT instance, and puts the result back in the newtype:

instance MonadBaseControl IO Foo where
  type StM Foo a = a 
  liftBaseWith f = Foo $ liftBaseWith $ \q -> f (q . unFoo)
  restoreM = Foo . restoreM 

Note that if StM wasn't an associated type family, you could do something like

newtype Foo a = Foo { unFoo :: ReaderT Int IO a } 
  deriving (Monad, Applicative, Functor, MonadBase IO, MonadBaseControl IO)

type instance StM Foo a = a 


来源:https://stackoverflow.com/questions/28137838/creating-monadbasecontrol-instance-for-newtype

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!