2015-09-27 9 views
7

は、私が持っているとしましょう。これはレンズなしで可能です:レンズ

eg1 :: T a (b -> c) -> b -> T (a, b) c 
eg1 (T foo bar) b = T (foo, b) (uncurry bar) 

しかし、私はレンズでこれを行うことができますか?

eg :: T a (b -> c) -> b -> T (a, b) c 
eg t b = t & foo %~ (, b) & bar %~ uncurry 
+1

レンズではそうしません。 – dfeuer

+2

ここでは奇妙なことがいくつかあります。まず、 'a - > b'に' a'のレンズを作ることはできないことに注意してください。第2に、 'Tuple a = Tuple a a'ではレンズを作ることはできませんが、* traversal *を行うことができます。 –

+0

@ J.Abrahamsonあなたは展開できますか? 'Tuple a = Tuple a a'の探索は何でしょうか? – user2141650

答えて

6

あなたはTのため自動的に生成されたレンズを使用してこれを行うことはできません。チェックを発生すると、次は動作しません。あなたは、物事を少しストレッチしたい場合は、まず、あなたが(自動的に)T'のためのタイプを変えるレンズを構築し、同型を通じてタイプT a bの値を変更するためにそれらを使用するttを使用することができます

data T' a b c = T' { _foo' :: c, _bar' :: a -> b} 

tt :: Iso (T a b) (T a' b') (T' a b a) (T' a' b' a') 
tt = dimap (\(T x g) -> T' x g) (fmap (\(T' x g) -> T x g)) 

を定義することができます。例えば

は、引数を少し再配置、あなたは

eg :: b -> T a (b -> c) -> T (a, b) c 
eg b = over tt $ (foo' %~ (,b)) . (bar' %~ uncurry) 

を書くことができますがTであまり周りに大騒ぎする必要がない場合は可能性が良くなる別のアプローチは、newtypeとしてそれを定義することですT'周り:

newtype T a b = T { getT :: T' a b a } 

次にあなたがIsoをスキップすることができますし、物事を構成します。引数を同じように並べ替えます。

eg' :: b -> T a (b -> c) -> T (a, b) c 
eg' b = T . (foo' %~ (,b)) . (bar' %~ uncurry) . getT 
+1

'over'は' from 'ブラケットの代わりに直接使用することができます: 'y = over tt(\(T' xf) - > T '(x、y)(uncurry f))' – duplode

+0

@duplode、good point 。一定。 – dfeuer

+0

@duplode、実際、私はその仕事をまったくしていないようです。私はブラケット接近のアプローチに戻りましたが、あなたがそれをより良くする方法を示すことができれば、私はすべての耳です。 – dfeuer

関連する問題