2016-03-28 32 views
3

kayıt işlevinin geri alınması Sum of Products yaklaşımında, kayıt fonksiyonu nasıl alınır? kayıt veri türü ile aşağıda bir örnek kodu (ghc 7.10.3):Genel SOP

{-# LANGUAGE DeriveGeneriC#-} 
import qualified GHC.Generics as GHC 
import Generics.SOP 
data Rec = Rec { frec :: Int, srec :: Maybe String} 
    deriving (Show, GHC.Generic) 

instance Generic Rec  -- empty 
instance HasDatatypeInfo Rec 

bize GHCi isteminde DataTypeInfo görelim: frec ve srec bir yapıcı FieldInfo sahiptir tip FieldInfo her iki olduklarını görüyoruz

*Main> datatypeInfo (Proxy :: Proxy Rec) 
ADT "Main" "Rec" (Record "Rec" (FieldInfo "frec" :* (FieldInfo "srec" :* Nil)) :* Nil) 

hangi fieldName dizesini string olarak alır. Yani, frec :: Rec -> Int ve gerçek işlevlerini elde etmek için herhangi bir yol göremiyorum. Ayrıca show example'a da baktım ama kayıt fonksiyonlarını kullanmıyor.

Kayıt işlevlerini nasıl alacağınız hakkında işaretçilerden memnun kalacaksınız (HList '[(Rec -> Int), (Rec -> Maybe String)] türünde HList olabilir)). Ben yaklaşım user2407038 kullanarak projeksiyonlar dışına fonksiyonlarını nasıl kurulacağı hakkında tipi knot kadar bağlıyım soru

için

Zeyilname dışarı hazırladı. Yani, daha fazla soruya eklemek ister olacaktır: Biz Rec yapıcı SOP yaklaşım kullanarak aşağıda bir işlev gibi yaratırım nasıl - ikimiz de rekor alan adını yanı sıra burada işlevini kullanın:

[ ("frec" ++) . show . frec, ("srec" ++) . show . srec] 

cevap

5

generics-sop kütüphane Ürünlerin toplamı ile çalışmak için genel kombinatorleri kullanır, bu nedenle bu kombinatorleri kullanarak böyle bir işlev yazmalısınız.

Tek bir sorun var - generics-sop, tür düzeyinde kayıtlar vs. yapıcılar hakkında herhangi bir bilgi içermez, bu nedenle işleviniz hala kısmi olacaktır (GHC generic Rep'dan kazmadığınız sürece).

Bu örnek için kısmi işlev yoluna gideceğim. O kütüphanede dahil edilmelidir gibi görünüyor, ama değil

data (:*:) f g x = f x :*: g x deriving (Show, Eq, Ord, Functor) 

(ya da ben bulamıyorum):

Öncelikle, bu veri türü gerekir.

fonksiyon tipi

recordSelectors :: forall t r . (Code t ~ '[ r ], Generic t, HasDatatypeInfo t) 
       => Proxy t -> Maybe (NP (FieldInfo :*: (->) t) r) 

kısıtlama Code t ~ '[ r ] sadece t üretimleri temsil toplamı a tek bir listesi (bir kurucu) olduğunu söyler olacaktır. Dönüş türü, r (kayıt alanı türleri listesi) listesinden ve t -> x her x türünde r numaralı ürüne ait bir üründür.

Bir uygulama fonksiyonu verilen veri türü belirler İşte

case datatypeInfo (Proxy :: Proxy t) of 
    ADT _ _ (Record _ fields :* Nil) -> Just $ 
     hzipWith (\nm (Fn prj) -> nm :*: (unI . prj . K . (\(Z x) -> x) . unSOP . from)) 
       fields 
       projections 
    _ -> Nothing 

rekor gerçekten ve aksi Nothing döndürür.Bu bir kayıt ise, kayıt alanlarını ve projections (kitaplık tarafından tanımlanmış), türün için temel olarak yalnızca NP '[ Code Rec -> Int, Code Rec -> Maybe String ] olan rasgele bir genel ürün için projeksiyonları tanımlayan zip dosyasıdır. Tüm kalan "gerçek" projeksiyonlar elde etmek için her projeksiyon ile from işlevini oluşturmaktır. Diğerleri (Fn, unSOP, vb.) Sadece kimliklerdir. Eğer sadece kayıt projeksiyon fonksiyonlarını istiyorum çıkıyor yana


, sans isimleri işlev, bu daha da kolaydır. Ve şimdi işlev kısmi değil - herhangi bir kurucu türü "kayıt projeksiyonları" var.

recordSelectors' :: forall t r . (Code t ~ '[ r ], Generic t) 
       => Proxy t -> NP ((->) t) r 
recordSelectors' _ = hmap (\(Fn prj) -> unI . prj . K . (\(Z x) -> x) . unSOP . from) 
          projections 
+0

Projeksiyonun kendiliğinden algılanmaması ve fieldInfo'nın göz ardı edilmesi kayıt işlevini almak için yeterli olur mu? Dediğiniz gibi, burada 'projeksiyonlar' türü 'NP' [Kod Rec -> Int, Kod Rec -> Belki Dize] 'dir. Ayrıca, 'Rep a = SOP I (Kod a))'. Bunu 'to' ile eşleştirmeniz bize '' bir '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'işlevi ile bir eşleştirmeli. İşte bu yüzden: *: 'için ihtiyaç konusunda kafam karıştı. Burada daha fazla bilgi için takdir edeceksiniz. – Sal

+0

Ayrıca, özellikle 'ghci' türündeki projeksiyonların türünü nasıl hesapladınız? Bu adım denemede çok yardımcı olacaktır. – Sal

+0

Üzgünüm - Ben * ve * isimlerini istediğini sanmıştım. Gerçekten de, sadece NP ((->) t) r 'olabilir - bu sadece fonksiyonlardır. Ayrıca, genel tip hakkında anlayışımı temel alarak, sadece kafamın içinde GHCi'deki türü hesaplamamıştım. Ancak ghci'ye, örneğin, örn. ': t projeksiyonları :: (Kod Rec ~ '[xs]) => NP (Projeksiyon f xs) xs' - tür," projeksiyonlar "ın genel türüdür ve kısıtlama, sorunda kullanılanla aynıdır. '' NP (Projeksiyon f '[Int, Belki Dize])' [Int, Belki Dize] 'diyor. – user2407038

İlgili konular