为newtype创建MonadBaseControl实例 [英] creating MonadBaseControl instance for newtype

查看:83
本文介绍了为newtype创建MonadBaseControl实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有简单的newtype声明

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

我想创建MonadBaseControl IO的Foo实例。它应该很容易,因为ReaderT Int IO已经是MonadBaseControl IO的一个实例。但是,使用GeneralizedNewtypeDeriving自动派生它不起作用,因为MonadBaseControl类具有关联的类型。



如何为Foo编写MonadBaseControl IO实例? defaultLiftBaseWith和defaultRestoreM应该是有帮助的,但是解密它们的类型有点困难。

既不是基本monad,也不是monad变换器。 defaultLiftBaseWith 在这里不会有帮助,因为您希望 Foo 的实例与<$ code> ReaderT Int IO 。



首先,使用GND获取无聊的实例:

  { - #LANGUAGE GeneralizedNewtypeDiving##} 

导入Control.Monad.Trans.Control
导入Control.Monad.Base
导入Control.Monad.Reader
导入控制。应用

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

MonadBaseControl IO 的实例只删除newtype,使用 ReaderT 实例,并将结果放回新类型:

 实例MonadBaseControl IO Foo其中
类型StM Foo a = a
liftBaseWith f = Foo $ liftBaseWith $ \q - > f(q。unFoo)
restoreM = Foo。 restoreM

请注意,如果 StM 不是关联类型的家庭,你可以做一些类似的事情:

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

类型实例StM Foo a = a


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.

解决方案

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 

这篇关于为newtype创建MonadBaseControl实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆