2016-10-15 16 views
6

için Uygulayıcı örneği yazarken <*> nasıl yazılır Haskell Book, "Bölüm 22. Okuyucu" 'da bir alıştırma ile sıkışıp kaldım. Egzersiz "Reader için uygulamalı uygulamak" diyor ve aşağıdaki verir:Okuyucu r

{-# LANGUAGE InstanceSigs #-} 

newtype Reader r a = 
    Reader { runReader :: r -> a } 

instance Applicative (Reader r) where 
    pure :: a -> Reader r a 
    pure a = Reader $ ??? 

    (<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b 
    (Reader rab) <*> (Reader ra) = Reader $ \r -> ??? 

aksi GHC Hayır" şikayetçi oldu çünkü (I Functor örneği yazdım ben de bir Functor örneğini yazdıktan sonra pure yazabiliyordu)" ‘Applicative (Reader r)’ için örnek bildirisinde bir örnek beyanının süper sınıf kaynaklanan (Functor (Reader r)) … için örnek:

{-# LANGUAGE InstanceSigs #-} 

newtype Reader r a = 
    Reader { runReader :: r -> a } 

instance Functor (Reader r) where 
    fmap f (Reader x) = Reader (f . x) 

instance Applicative (Reader r) where 
    pure :: a -> Reader r a 
    pure a = Reader $ \_ -> a 

    (<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b 
    (Reader rab) <*> (Reader ra) = Reader $ \r -> ??? 

Ama ??? kısmı ile sıkıştım. Biz yapmanız gerekenleri açıklayan edeceğiz uygulamak fonksiyonunun tanım sizin için başlatılan got

ve kod yazmak:

kitap şu ipucu verir. Yukarıdaki Okuyucu’nın türünün paketini açarsanız, aşağıdakileri alırsınız.

<*> :: (r -> a -> b) 
    -> (r -> a) 
    -> (r -> b) 

-- contrast this with the type of fmap 

fmap :: (a -> b) 
    -> (r -> a) 
    -> (r -> b) 

Peki, fark nedir? Fark, fmap'un aksine apply'un r türünde bir argümanını almasıdır.

Bunu yapın.

Evet, ancak nasıl yapmalı? yazılan delikleri kullanarak derleyici, ??? türünün b olması gerektiğini bildirir. Ama hala bir r alır ve rab ve ra verilen b türünde bir şey döndüren bir lambda ifade inşa edebilirsiniz göremiyorum. Eğer kapsamında olan parçalara baktığımızda

+0

Ayrıca, bu kitabı satın alamayacak olanlar için 'Reader' veri türünün tanımını da sağlayabilir misiniz? –

+0

@Rhymoid Bu biraz sert. Ne 'Reader', genel bilgidir, ne de olsa. – duplode

+0

Eksik Reader türü için özür dilerim, yukarıdaki soruya ekledim. –

cevap

7

,

rab :: r -> (a -> b) 
ra :: r -> a 
r :: r 

ve b hedefi türü, sen tek yolu iki argümanları rab uygulayarak dışarı is a b alabilirsiniz görebilirsiniz.

Reader rab <*> Reader ra = Reader $ \r -> rab _ _ 

Şimdi, ilk delik r bir türü olan ve yalnızca kapsamında tane r var.

Reader rab <*> Reader ra = Reader $ \r -> rab r _ 

kalan delik a bir türü vardır. Eğer kapsamında tek a, ra dönüş değeri olan

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra _) 

ve ra 'ın argümanı bir kez daha yalnızca bir seçim var kendisi için bir r, olmalıdır. rab ve ra ikisi de bir argüman olarak r almalarını

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r) 

dikkat edin.Oluşturulan bir Reader hesaplamasındaki tüm adımlar aynı ortama erişebilir.

Bu arada, bu tanım, ünlü S combinator eşdeğer <*> yapar (ve pure K olan).