再次感謝您的幫助!如何縮放monad變壓器?
我正在廣泛使用E. Kmett的鏡頭庫,以避免X/Y問題我將解釋一些上下文。
我工作的一個可擴展的文本編輯器,並希望提供擴展作者用單子DSL,一個Alteration
是一個StateT在Store
類型,它基本上存儲整個文本編輯器單子轉換堆棧。在Store
內部是Editor
其具有Buffer
s。用戶可以指定Alteration
來對整個商店進行操作,但爲了簡化操作,我還提供了BufAction
,它僅通過一個緩衝區進行操作。
我打算用一種叫做bufDo
助手運行在BufAction
在每個Buffer
實施這一點,並運行於「專注」 Buffer
一個BufAction
一個focusDo
。下面是一些背景:
data Store = Store
{ _event :: [Event]
, _editor :: E.Editor
, _extState :: Map TypeRep Ext
} deriving (Show)
data Editor = Editor {
_buffers :: [Buffer]
, _focused :: Int
, _exiting :: Bool
} deriving Show
data Buffer = Buffer
{ _text :: T.Text
, _bufExts :: Map TypeRep Ext
, _attrs :: [IAttr]
}
newtype Alteration a = Alteration
{ runAlt :: StateT Store IO a
} deriving (Functor, Applicative, Monad, MonadState Store, MonadIO)
newtype BufAction a = BufAction
{ runBufAction::StateT Buffer IO a
} deriving (Functor, Applicative, Monad, MonadState Buffer, MonadIO)
這是我提出的bufDo
和focusDo
實現:
bufDo :: ???
bufDo = zoom (buffers.traverse)
-- focusedBuf is a Lens' over the focused buffer (I just 'force' the traversal using ^?! in case you're wondering)
focusDo :: ???
focusDo = zoom focusedBuf
這是有道理的在我的頭上,並得到接近類型檢查,但是當我嘗試添加類型他們我有點糊塗了,GHC暗示一些東西,我結束了這一點,這是遠離優雅:
bufDo :: (Applicative (Zoomed BufAction()), Zoom BufAction Alteration Buffer Store) => BufAction() -> Alteration()
focusDo :: (Functor (Zoomed BufAction()), Zoom BufAction Alteration Buffer Store) => BufAction() -> Alteration()
這使得GHC快樂對於那些定義,但是當我嘗試實際使用其中任何一個,我得到這些錯誤:
- No instance for (Functor (Zoomed BufAction()))
arising from a use of ‘focusDo’
- No instance for (Applicative (Zoomed BufAction()))
arising from a use of ‘bufDo’
環顧四周,好像我可能需要指定放大的情況下,但我不知道怎麼和去做。
任何人有想法嗎?如果你能解釋爲什麼我需要Zoom實例(如果是這種情況),我也會喜歡它。
乾杯!
這實質上是[這個問題]重複(http://stackoverflow.com/questions/29407289/lens-zooming -newtype)。 – freestyle
我看到了一個,但仍然有點困惑,他們給出了一個解決方案,但不能很清楚地解釋它。 –