2016-03-28 30 views
3

Kötü başlık için özür dilerim. Functor örneğini tanımlamaya çalıştığım sorunlu bir veri türüm var.Haskell: bu veri türünden functor?

Yani temelde, bende ne

sample_logp :: s a -> a 

olan bir şey, ve bu

sample_logp :: s b -> b 

için

(a -> b) 

kullanılarak dönüştürülmesi gerektiğini. Aşağıdaki kod bunu tam olarak gerçekleştirmez ve yalnızca

'da başarılı olur.

data Model s a = Model { 
    sample_logp :: s a -> a 
} 

instance Functor (Model s) where 
    fmap f m = Model { 
    sample_logp = sample_logp' 
    } where sample_logp' x = (f . (sample_logp m)) x 

Mümkün olanı deniyor muyum? Öyleyse, bu kod bunu başarmak için nasıl güncellenebilir?

+8

Bir functor olamaz: 'a' hem kovaryant hem de kontravaryant pozisyondadır. – zakyggaps

+0

Teşekkür ederiz! Bu durumda, bunu başarabilecek başka tip sınıf var mı? – tero

+3

[Profunctor] 'ı (http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor.html) kontrol edebilirsiniz, ancak tasarım seçimi, 's' nin ne olduğuna bağlıdır. – zakyggaps

cevap

9

Buradaki standart yaklaşım daha fazla tip değişken eklemek.

data Model s a b = Model { 
    sample_logp :: s a -> b 
} 

Tür değişkenlerini ayırdıktan sonra, daha fazla araca erişebilirsiniz. Profunctor sınıfı burada uygun. (Ben bu sistemde ghc olmadığı için typechecked değil -. Yorum yaptığım veya uygulama kapalıysa sadece bunu düzeltmek)

instance (Functor s) => Profunctor (Model s) where 
    dimap f g (Model h) = Model $ g . h . fmap f 
    lmap f (Model h) = Model $ h . fmap f 
    rmap g (Model h) = Model $ g . h 

Şimdi, bir Model s a a sahip olduğu göz önüne alındığında, senin Model s a eşdeğer olan dimap bToA aToB kullanarak Model s b b'a dönüştürebilirsiniz.

Açıklamaların söylediğine göre, orijinal veri türünüz değişkendir, çünkü pozitif ve negatif konumlarda aynı tür değişkenini kullanır. Bu, her yönde dönüşüm işlevleri sağlamanız gerektiği anlamına gelir. Ekstra tip değişkeni eklemek, Profunctor gibi mevcut araçların avantajlarından faydalanmanızı sağlar. Yukarıdakilerin hepsi sen s için bildirdiğinden türlerini kullanan varsayımına dayanmaktadır


Not. s contravariant ise, o zaman chi'nin yorumunun söylediği gibi, orijinal türünüz için doğrudan Functor örneğini yazabilirsiniz. Bu olsa da, daha az yaygın bir durum.