2013-08-05 30 views
6

Ben ...Varoluşsal tipli lensleri kullanamamakta nasıl çalışıyoruz?

[1] varoluşsal nicelik makeLenses bozabilir açıklar de soru ilk defa Edward Kmett en mercek kitaplığı kullanarak ve oldukça güzel buluyor ama ben bir engelle karşılaştım ediyorum. Bir modada bir varoluşsallığı gerçekten kullanmak istiyorum.

Arka plan olarak, sınıf var: gerçek soru için

class (TextShow file, Eq file, Ord file, Typeable file) => File file where 
    fromAnyFile :: AnyFile -> Maybe file 
    fileType :: Simple Lens file FileType 
    path :: Simple Lens file Text.Text 
    provenance :: Simple Lens file Provenance 

, ben tip istiyorum:

data AnyFile = forall file . File file => AnyFile { _anyFileAnyFile :: File } 

Ve çizgisinde bir şeyler yazabilmek istiyorum arasında:

instance File AnyFile where 
    fromAnyFile (AnyFile file) = cast file 
    fileType (AnyFile file) = fileType . anyFile 
    path (AnyFile file) = path . anyFile 
    provenance (AnyFile file) = provenance . anyFile 

Bu işe yaramazsa, bir nedenle açıklanan [1]. Ben -ddump-splices ile derleyerek bilgi ayıklama için GHC sorarsanız, ben alıyorum:

Haskell/Main.hs:1:1: Splicing declarations 
    makeLenses ''AnyFile ======> Haskell/Main.hs:59:1-20 

ek yeri kendisi hiçbir beyanlar onun tarafından üretilen bana gösterecek şekilde boştur. Bu kısmı beklediğimi ve anladığımı anladım [1].

Bilmek istediğim şey, bunu nasıl yapabileceğimizdir - problemi çözmek için ne yapabilirim? Bu konuda yüzme önlemek için ne yapabilirim? Yapılarımın herhangi bir parçasını bir oluşturulmuş lensler yolu ile erişebilmeyi, ancak Set AnyFile gibi türlerde başka türlerim olduğu için, bir lens ile AnyFile içeriğine erişemedikçe bunu yapamam.

[1] En kötü durumda Existential quantifier silently disrupts Template Haskell (makeLenses). Why?

+0

Sadece merak edenler için, yaptığım şey aşağıdaki öneriyi kullanmaktı; objektif olması gereken tanım (\ (AnyFile dosya) -> dosya) (\ _ value -> AnyFile value). –

cevap

7

, her zaman hiç Şablon Haskell dayanmadan lensleri kendiniz uygulayabilir. bir alıcı ve türüne uygun bir kurucu işlevi Verilen örnek için

, sen lens işlevini kullanarak bir lens oluşturabilirsiniz:

lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b 

Bu etkili ve verimli bir seçenek olmayabilir inanıyoruz, ama kesinlikle var en kolay.

I (genel olarak varoluşsal türleriyle veya) dava için bunun nasıl biliyorum ama burada bir kayıt kullanılarak önemsiz bir örnek yoktur:

data Foo = Foo { _field :: Int } 
foo = lens _field (\ foo new -> foo { _field = new }) 

Umarım bu uygulamak için yeterince iyi bir fikir göstermektedir koduna.

+0

Hmm ... Lens işlevi hakkında bilgi vermedim. Teşekkür ederim! Dokümanlar daha çok, büyük. :) Şimdi bir şey yapmaya çalışıyorum ve varsa cevap kabul edecektir. :) –

+1

En azından benim versiyonumda olan objektifin türü "Functor f => (s -> a) -> (s -> b -> t) -> (a -> fb) -> gibi görünüyor -> ft Tamam. Bir çeşit devam eden şey gibi görünüyor, muhtemelen anlayabiliyorum ... –

+0

Oh anlıyorum. Sağ. Sadece ilk iki parametreye ihtiyacım var çünkü kalanlar objektifin kendisinin bir parçası ... Belgeler belki de bana neler olduğunu açıklayabilir. –