2015-04-02 71 views
3

我很感興趣,讓我的單子轉換堆棧縮放功能,其定義方式如下:鏡頭:變焦NEWTYPE

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

AwesomeState是深度嵌套的記錄,因此使用變焦會大大幫助我更新一些字段。但問題是縮放無法用於我的新類型。

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

我發現如何使放大的定製NEWTYPE RWST實例,但試圖使其適應我的NEWTYPE沒有給我結果

的RWST例如一個例子可以在這裏找到:http://lpaste.net/87737

有沒有一種方法可以開始使用我的monad變壓器堆棧進行縮放?我需要做些什麼才能做到這一點?如果我應該像RWST示例那樣實現縮放/縮放,那麼我需要一個指示器來指出如何做到這一點,因爲我試過並且未能這樣做。

+1

這實質上是[這個問題]的重複(http://stackoverflow.com/questions/29188217/lens-zoo間模棱兩可變量)。我猶豫重複投票,因爲這個問題比另一個更清楚。 – 2015-04-02 07:40:36

回答

2

我建議作出明確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