镜头:变焦新型 [英] Lens: zooming newtype

查看:88
本文介绍了镜头:变焦新型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有兴趣为我的monad变压器堆栈获取 zooming 功能,该功能的定义如下:

I'm interested in getting a zooming functionality for my monad transformer stack which is defined the following way:

newtype Awesome a = Awesome (StateT AwesomeState (ExceptT B.ByteString IO) a)
  deriving (Functor, Applicative, Monad
           , MonadIO, MonadError B.ByteString
           , MonadState AwesomeState)

我的 AwesomeState 是深层嵌套的记录,因此使用zoom将极大地帮助我更新某些字段.但是问题是缩放对于我的新类型无法立即使用.

My AwesomeState is deeply nested record, so using zoom would greatly help me in updating some of the fields. But the problem is that zoom doesn't work out of the box for my newtype.

Couldn't match type ‘Control.Lens.Internal.Zoom.Zoomed Awesome’ 
with ‘Control.Lens.Internal.Zoom.Zoomed m0’

我找到了一个示例,该示例如何制作Zoom的自定义新类型RWST实例,但尝试使其适应我的新类型却没有结果

I found an example of how to make a custom newtype RWST instance of Zoom but trying to adapt it to my newtype gave me no results

可以在此处找到RWST示例: http://lpaste.net/87737

The RWST example can be found here: http://lpaste.net/87737

有没有一种方法可以在我的monad变压器堆栈中开始使用缩放?为此我需要做什么?如果我应该像RWST示例中那样实现Zoomed/Zoom,那么我需要一个如何做到这一点的指针,因为我尝试过但失败了.

Is there a way I could start using zoom with my monad transformer stack? What would I need to do in order to achieve that? If I should implement the Zoomed/Zoom like in RWST example then I need a pointer of how to do that because I tried and failed to do so.

推荐答案

我建议明确显示Awesome的状态:

I'd suggest to make state of Awesome explicit:

{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, TypeFamilies,
    FlexibleInstances, FunctionalDependencies #-}
import Control.Applicative
import Control.Monad.Error
import Control.Monad.State
import Control.Lens
import Control.Lens.Zoom
import Control.Lens.Internal.Zoom

data AwesomeState = AwesomeState
    { _someRecord :: String
    -- ...
    }

$(makeLenses ''AwesomeState)

newtype Awesome s a = Awesome (StateT s (ErrorT String IO) a)
  deriving ( Functor, Applicative, Monad
           , MonadIO, MonadError String
           , MonadState s)

然后您可以为其定义Zoom实例,如下所示:

Then you can define Zoom instance for it as follows:

type instance Zoomed (Awesome s) = Focusing (ErrorT String IO)

instance Zoom (Awesome s) (Awesome t) s t where
    zoom l (Awesome m) = Awesome (zoom l m)

那么您将拥有

zoom someRecord :: Awesome String a -> Awesome AwesomeState a

这篇关于镜头:变焦新型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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