镜头:变焦新型

ksa*_*jev 5 haskell zooming newtype haskell-lens

我有兴趣为我的 monad 转换器堆栈获得缩放功能,该功能定义如下:

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

我的AwesomeState是深度嵌套的记录,因此使用缩放将极大地帮助我更新某些字段。但问题是,对于我的 newtype 来说,zoom 不能开箱即用。

Couldn't match type ‘Control.Lens.Internal.Zoom.Zoomed Awesome’ 
with ‘Control.Lens.Internal.Zoom.Zoomed m0’
Run Code Online (Sandbox Code Playgroud)

我找到了一个示例,说明如何制作 Zoom 的自定义 newtype RWST 实例,但尝试使其适应我的 newtype 没有结果

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

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

Pet*_*lák 4

我建议明确说明Awesome

{-# 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)
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

然后你就会有

zoom someRecord :: Awesome String a -> Awesome AwesomeState a
Run Code Online (Sandbox Code Playgroud)