所以,这是一个具体的想法:我正在编写一个Scrabble游戏AI,并且在计算棋盘上所有可能移动的过程中,我必须计算每个棋盘方块的一堆中间值。我想以一种可组合的方式缓存这些中间值。
所以,更抽象地说:
没有缓存,我有f :: w a -> w b
,g :: w b -> w c
,其中w
可以是任何仿函数,但在我的情况下是Scrabble board数据类型。添加缓存后,我有f' :: m (w a) -> m (w b)
和g' :: m' (w b) -> m' (w c)
,其中m
和m'
是包含缓存状态的 monads 数据类型*。但现在我无法撰写f'
和g'
。
我不太熟悉monad变换器,但听起来好像我在这里使用它,我需要反复lift
我的monadic函数取决于我在缓存函数组合链中的深度。例如。如果我有f' . g' . h'
,则h'
的实施需要lift . lift . lift get
之类的内容。我在这里偏离基地吗?原则上,f'
,g'
和h'
是无关的,并且不需要了解彼此的缓存状态。是否有更好的方法来做反映这种独立性的事情?
*我不认为他们必须是monad,因为我不打算让其他功能修改m
和m'
。它们仅对f'
和g'
“隐私”。
答案 0 :(得分:1)
一般情况下,m (w a) -> m (w b)
和m' (w b) -> m' (w c)
不会撰写。
如果m
是Functor
(或其他协变仿函数)并且m'
是“尖头”(即它具有返回/纯函数),那么您可以撰写获取{ {1}}。
此外,如果m (w a) -> m (m' (w c))
和m
并且两者都被提升为一个共同的monad(即某些monad存在函数m'
和m a -> t a
),那么你可以使用那些提升和连接以生成m' a -> t a
类型的组合。
独立性和构图是竞争目标 - 两者都很好 - 但是,要构成两件事,他们必须具有“匹配的形状”,这些形状不会让它们独立变化。