получить набор кортежей с объективом через ReaderT - PullRequest
0 голосов
/ 23 января 2020

Я хотел бы поиграть с кортежами и линзами следующим образом:

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

сможет изменить входной кортеж для его подмножества ...

псевдокод будет чем-то как это:

zoom (_1,_3,_4)

Ответы [ 2 ]

4 голосов
/ 24 января 2020

Как отмечает @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)
1 голос
/ 24 января 2020

Ответ К. А. Бура вполне достаточно, так что здесь идет небольшой кусочек. Поскольку magnify нужен только геттер (а не полноценная линза), можно express myfct' в терминах _1 и друзей с помощью 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)

Хотя это не особенно эргономично c, это, возможно, немного ближе к духу вашего псевдокода.

...