gpt4 book ai didi

haskell - 如何缩放 monad 转换器?

转载 作者:行者123 更新时间:2023-12-03 03:59:35 25 4
gpt4 key购买 nike

再次感谢您的帮助!

我正在广泛使用 E. Kmett 的镜头库,为了避免 X/Y 问题,我将解释一些背景信息。

我正在开发一个可扩展的文本编辑器,并希望为扩展编写者提供 monad DSL,Alteration 是一个 monad 转换器堆栈,在 Store 上带有 StateT type,它基本上存储了整个文本编辑器。在Store内部是一个Editor,它有Buffer。用户可以指定一个 Alteration 来对整个存储进行操作,但为了简化事情,我还提供了一个 BufAction ,它仅在单个缓冲区上运行。

我计划通过使用名为 bufDo 的帮助程序来实现此目的,该帮助程序在每个 Buffer 上运行 BufActionfocusDo 在“聚焦”Buffer 上运行 BufAction。以下是一些背景信息:

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)

这是我建议的 bufDofocusDo 实现:

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 指定一个实例,但我不确定如何做到这一点。

有人有想法吗?如果您能解释为什么我需要 Zoom 实例(如果是这样的话),我也会很高兴。

干杯!

最佳答案

似乎有一个 Zoomed 类型族,用于指定缩放时我们将获得什么样的“效果”。在某些情况下,monad 转换器的 Zoomed 类型实例似乎搭载在底层 monad 的 Zoomed 上,例如

type Zoomed (ReaderT * e m) = Zoomed m

鉴于 AlterationBufAction 只是状态转换器上的新类型,也许我们可以这样做:

{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}
{-# language MultiParamTypeClasses #-}

type instance Zoomed BufAction = Zoomed (StateT Buffer IO)

然后我们必须提供 Zoom 实例。 Zoom 是一个多参数类型类,四个参数似乎是原始 monad缩小 monad原始状态>,缩小状态:

instance Zoom BufAction Alteration Buffer Store where
zoom f (BufAction a) = Alteration (zoom f a)

我们只是解开 BufAction,使用底层 monad 进行缩放,然后包装为 Alteration

此基本测试类型检查:

foo :: Alteration ()
foo = zoom (editor.buffers.traversed) (return () :: BufAction ())
<小时/>

我相信您可以避免定义 Zoom 实例并拥有一个特殊用途的 zoomBufActionToAlteration 函数

zoomBufActionToAlteration :: LensLike' (Zoomed (StateT Buffer IO) a) Store Buffer 
-> BufAction a
-> Alteration a
zoomBufActionToAlteration f (BufAction a) = Alteration (zoom f a)

但是,如果您有很多不同的可缩放功能,那么记住每个缩放功能的名称可能会很麻烦。这就是类型类可以提供帮助的地方。

关于haskell - 如何缩放 monad 转换器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41130226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com