Ответ 1
Foo
не является "базовой" монадой или монадным трансформатором. defaultLiftBaseWith
здесь не будет полезен, так как вы хотите, чтобы экземпляр для Foo
был идентичен экземпляру для ReaderT Int IO
.
Сначала используйте GND для получения скучных экземпляров:
{-# 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)
Экземпляр для MonadBaseControl IO
просто удаляет новый тип, использует функции из экземпляра ReaderT
и возвращает результат в newtype:
instance MonadBaseControl IO Foo where
type StM Foo a = a
liftBaseWith f = Foo $ liftBaseWith $ \q -> f (q . unFoo)
restoreM = Foo . restoreM
Обратите внимание, что если StM
не было ассоциированным типом семейства, вы могли бы сделать что-то вроде
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO, MonadBaseControl IO)
type instance StM Foo a = a