2016-03-20 30 views
1

deriveJSON'dan sonra modellenen genel türetmenin nasıl yapılacağını anlamaya çalışıyorum. Ben aşağıda rekor tarzı veri yapıcısı kullanarak basit bir türü tanımlanmıştır: Yapmak istediğim ne olacakGenel adlarda kayıt adı ve işlevine erişme

data T = C1 { aInt::Int, aString::String} deriving (Show,Generic) 

Yukarıdaki veriler kurucular alır fonksiyonu derive jenerik tanımlamaktır ve kayıt adları ve kullanan bir oluşturucu çıkışı Ben çözemiyorum ne

{-# LANGUAGE DeriveGeneriC#-} 

import GHC.Generics 

data T = C1 { aInt::Int, aString::String} deriving (Show,Generic) 

-- Some kind of builder output - String here is a stand-in for the 
-- builder 
class ABuilder a where 
    f :: a -> String 

-- Need to get the record field name, and record field function 
-- for each argument, and build string - for anything that is not 
-- a string, we need to add show function - we assume "Show" instance 
-- exists 
instance ABuilder T where 
    f x = ("aInt:" ++ (show . aInt $ x)) ++ "," ++ ("aString:" ++ (aString $ x)) 

nasıl olsun: fonksiyonları - - sadece bir oyuncak kodu, ABuilder jenerik yüzden kayıt sözdizimi ile herhangi bir veri türü (gibi Aeson yılında deriveJSON) için kullanabilirsiniz yapmak istiyorum kayıt adı ve işlevi. İşte benim denemem ghci 7.10.3. Veri türü adını alabilirim, ancak kayıt adlarını ve işlevlerini nasıl alacağımı anlayamıyorum.

$ ghci Test.hs 
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help 
[1 of 1] Compiling Main    (Test.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> datatypeName . from $ (C1 {aInt=1,aString="a"}) 
"T" 
*Main> :t from (C1 {aInt=1,aString="a"}) 
from (C1 {aInt=1,aString="a"}) 
    :: D1 
     Main.D1T 
     (C1 
      Main.C1_0T 
      (S1 Main.S1_0_0T (Rec0 Int) :*: S1 Main.S1_0_1T (Rec0 String))) 
     x 
*Main> 

ben kaydı adı ve Generics işlevi almak için nasıl işaretçileri takdir edecektir. TemplateHaskell, 'un Generic örneğini tanımlamak için daha iyi bir yaklaşımsa, bunun nedenini anlayacağım. Çözüm basitse, derleme zamanında bunu çözmek için Generics'a bağlı kalmayı umuyorum. Aeson'un deriveJSON parçası için TemplateHaskell kullandığını fark ettim. İşte bu yüzden burada kaybolan bir şey olup olmadığını görmek için TemplateHaskell hakkındaki sorum var (ghc 7.10.3 kullanıyorum ve eski sürümlerle geriye dönük uyumluluk gerekmez). İşte

+0

bkz repl itibaren

{-# LANGUAGE DeriveGeneric, TypeOperators, FlexibleContexts, FlexibleInstances #-} import GHC.Generics data T = C1 { aInt::Int, aString::String} deriving (Show,Generic) class AllSelNames x where allSelNames :: x -> [String] instance (AllSelNames (a p), AllSelNames (b p)) => AllSelNames ((a :*: b) p) where allSelNames (x :*: y) = allSelNames x ++ allSelNames y instance Selector s => AllSelNames (M1 S s f a) where allSelNames x = [selName x] 

, meta verileri temsil eden türlerin (yani. C1_0T, S1_0_0T vb.) uygun sınıfların örnekleri vardır ("Datatype", "Oluşturucu", "Seçici"). Bu örnekler, bu meta verilere erişmenizi sağlayan şeydir. Tüm jenerik örneklerde olduğu gibi, farklı jenerik kurucuları işlemek için bir sınıfa ihtiyacınız olacak. – user2407038

+0

@ user2407038, evet, biliyorum. Sorum şu, kayıt adlarına ve işlevlerine nasıl erişileceği ile ilgili. Şimdiye kadar gördüğüm genel örnekler bu senaryolara sahip değil. – Sal

+1

Hiç sihir yok - tiplerin yöntemlerini çağırın, yani [Seçici] (https://hackage.haskell.org/package/base-4.8.2.0/docs/GHC-Generics.html#t:Selector) uygun değerlerde. 'DatatypeName' kullandığınız tam olarak aynı. Herhangi bir kod sağlamadınız ki, artık söylemek zor. – user2407038

cevap

2

Sadece çırpılmış bir şey olduğunu bunu belirli bir yapıcı bağırsaklar verirsen bu almalısınız: Eğer `Generic` türetmek biz

*Main> let x = unM1 . unM1 $ from (C1 {aInt=1,aString="a"}) 
*Main> allSelNames x 
["aInt","aString"] 
+0

Buna cevap vermek için zaman ayırdığınız için teşekkür ederim. Kayıt fonksiyonunu açmak için, 'M1 {unM1 = K1 {unK1 = 1}} 'desen eşleşmesi yeterli olur ve' unK1' alır? – Sal

+0

Bu size işlevi değil, değeri verir. Eğer kayıtların yapraklarında atomik şeyleriniz varsa, karmaşık yapıların kendisiyse, onları “Rep” den geri döndürmek için onları geri göndermeniz gerekir. – sclv

İlgili konular