我有兴趣为我的monad变压器堆栈获取缩放功能,该功能通过以下方式定义:

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

我的AwesomeState是深层嵌套的记录,因此使用zoom将极大地帮助我更新某些字段。但是问题是缩放对于我的新类型无法立即使用。
Couldn't match type ‘Control.Lens.Internal.Zoom.Zoomed Awesome’
with ‘Control.Lens.Internal.Zoom.Zoomed m0’

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

RWST示例可在以下位置找到:http://lpaste.net/87737

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

最佳答案

我建议明确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)

然后,您可以为其定义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)

那你有
zoom someRecord :: Awesome String a -> Awesome AwesomeState a

关于haskell - 镜头: zooming newtype,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29407289/

10-13 07:33