通过 ReaderT 获取带镜头的元组子集

getting a tuple subset with lens over a ReaderT

我想这样玩元组和镜头:

myfct :: ReaderT (a,b,c,d,e) m a -> ReaderT (a,c,d) m a
myfct = zoom ...

能够将输入元组修改为其子集...

伪代码应该是这样的:

zoom (_1,_3,_4)

如@dfeuer 所述,您可能打算写:

myfct' :: Monad m => ReaderT (a,c,d) m a -> ReaderT (a,b,c,d,e) m a

这采取了一个只需要访问上下文 (a,c,d) 的操作,并将其提升为一个可以 运行 在提供 (a,b,c,d,e) 的更大上下文中的操作。这可以使用 magnify 编写,如下所示:

myfct' = magnify . to $ \(a,_,c,d,_) -> (a,c,d)

另一方面,如果您的意思是您所写的:

myfct :: Monad m => ReaderT (a,b,c,d,e) m a -> ReaderT (a,c,d) m a

然后你将不得不解释这应该做什么。特别是,如果您有访问 b :: String 组件的操作:

action :: Reader (Int,String,Int,Int,Int) Int
action = asks $ \(_,b,_,_,_) -> length (b :: String)

你想如何在没有 b :: String 的情况下 运行 它?

test' :: Int
test' = runReader (myfct action) (1,2,3)

perfectly suffices, so here goes just a little tidbit. Since magnify need just a getter (rather than a full-blown lens) one might express myfct' in terms of _1 and friends with the help of ReifiedGetter:

myfct' :: Monad m => ReaderT (a,c,d) m a -> ReaderT (a,b,c,d,e) m a
myfct' = magnify (runGetter $ (,,) <$> Getter _1 <*> Getter _3 <*> Getter _4)

虽然不是特别符合人体工程学,但这可能更接近您的伪代码的精神。