TLを使用して、DRを:それは/いずれかの任意newtype
(すなわち、このような抽象化のインスタンスを提供する)アンラップラップする抽象化のlens
ファミリーのいずれかを使用することが可能ですか?どのように包装の定型を排除し、アンラッピングレンズ
私は真実の物語に基づいて簡単な例で私の質問を動機づけます。
フォームの条件を表すために使用されるnewtype FreeMonoid a = FreeMonoid { asMap :: Map a Int }
:
a0 <> a1 <> ... <> an-1
我々はリストとして自由モノイドを表すことができますの
instance Ord a => IsList (FreeMonoid a) where
type Item (FreeMonoid a) = a
fromList xs = FreeMonoid $ Map.fromListWith (+) $ zip xs (repeat 1)
toList (FreeMonoid p) = do
(x, n) <- Map.toList p
genericReplicate n x
2つの例を、私は、次のnewtype
を定義すると仮定遊離モノオールは、和および生成物の配列のシーケンスである:
type FreeSum a = FreeMonoid (Sum a)
type FreeProduct a = FreeMonoid (Product a)
Sum
およびProduct
は、Data.Monoid
で定義されています。
fromListSum :: Ord a => [a] -> FreeSum a
fromListSum = fromList . (Sum <$>)
fromListProduct :: Ord a => [a] -> FreeProduct a
fromListProduct = fromList . (Product <$>)
をしかし、これは定型のかなり多くを持っている:今、次のように、私たちはFreeSum
と FreeProduct
ためfromList
とtoList
操作を定義することができます。 wrap
は(hypotetical)のいくつかの操作が
fromListW :: (Ord a, Wrapper f) => [a] -> FreeMonoid (f a)
fromListW = fromList . (wrap <$>)
ですWrapper
クラスは以下の通りであった::
wrap :: a -> f a
unwrap :: f a -> a
同様に、私は書くことができるようにしたいのですが、我々は単純に言うことができればよりよいだろう関数:
toListW :: (Ord a, Wrapper f) => FreeMonoid (f a) -> [a]
toListW = (unwrap <$>) . toList
レンズはControl.Lens.Wrapped
このような抽象化を提供するように思われる(この例ではSum
とProduct
がINSTAであるためそこにはタイプメスのネズミ!)。しかし、このモジュールの抽象概念を理解して使用しようとする私の試みは失敗しました。例:
fromListW :: (Ord a, Wrapped (f a)) => [a] -> FreeMonoid (f a)
fromListW = fromList . (Wrapped <$>)
のリストではないため、このフィールドは機能しません。
だから私の質問は次のとおりです。
- ドゥレンズは、この
Wrapper
クラスに似た抽象化を提供? - もしそうでなければ、レンズを使ってこの問題を解決できますか?
ありがとう:
toListW
実装では、同様の構造を持っているでしょう。どのように、なぜソリューションが機能するのかはまだ不明ですが、私はレンズに深く浸ってから理解が来ることを願っています。それまでのところ、[ここ](https://github.com/capitanbatata/sandbox/blob/master/pw-lenses/src/Coercions.lhs)は実用的なコードです。 –