2011-03-14 20 views
6

Şablon Haskell koduna bir işlev eklemem gerekiyor. İfade sözdizimini kullanıyorum: Bir işlev için örnek alınsın mı?

[|f|]
Bazı işlevler otomatik olarak çalışıyor gibi görünüyor. Ancak, bu özel biri için aşağıdaki erroe mesajı alıyorum:

 
    No instance for (Lift (String -> [Content])) 

nasıl bir işlev için bir asansör örneğini yapmak için hiçbir fikrim yok ve herhangi bir yararlı bilgi bulmak gibi olamaz. Birisi bana bir kaynağa işaret edebilir mi veya bana bunun genel olarak nasıl yapıldığına dair bir fikir verebilir mi? Bu arada, kendi özel örneğimi yıkıp kaldıramayacağımı göreceğim.

+0

(http://hackage.haskell.org/packages/archive/template-haskell/2.4.0.1/doc/html/Language-Haskell-TH: Burada Maybe için biri -Syntax.html # t: Kaldırma) (neredeyse hiç yok). Umarım yardımcı olur, ama muhtemelen olmaz :(Bir fonksiyon yazmak zorundasınız gibi görünüyor 'lift :: (String -> [Content]) -> Q Exp', yani, fonksiyonunuzu bir ifadeye çevirmek –

cevap

7

TH, daha fazla kod görmeden hata ayıklaması zor olsa da bir bıçak alacağım. Şimdi (ben hangi sürüm 7.0.2 olduğum GHCi bu kadar atabileceği

{-# Language TemplateHaskell #-} 

baz x = let f y = x + y 
    in [| f |] 

bez x = let f y = x + y 
    in [| \y -> f y |] 

boz x = [| \y -> x + y |] 

g x y = x + y 

byz x = [| g x |] 

:

foo.hs:

Biraz örnek kodlara bakalım geçerli Haskell Platformu) ile gemiyle:

$ ghci foo.hs -XTemplateHaskell 
*Main> :m +Language.Haskell.TH 
*Main Language.Haskell.TH> runQ (baz 2) 

<interactive>:1:7: 
No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
    arising from a use of `baz' 
Possible fix: 
    add an instance declaration for 
    (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
In the first argument of `runQ', namely `(baz 2)' 
In the expression: runQ (baz 2) 
In an equation for `it': it = runQ (baz 2) 
*Main Language.Haskell.TH> runQ (bez 2) 

<interactive>:1:7: 
    No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
     arising from a use of `bez' 
    Possible fix: 
     add an instance declaration for 
     (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) 
    In the first argument of `runQ', namely `(bez 2)' 
    In the expression: runQ (bez 2) 
    In an equation for `it': it = runQ (bez 2) 
*Main Language.Haskell.TH> runQ (boz 2) 
LamE [VarP y_0] (InfixE (Just (LitE (IntegerL 2))) (VarE GHC.Num.+) (Just (VarE y_0))) 
*Main Language.Haskell.TH> runQ (byz 2) 
AppE (VarE Main.g) (LitE (IntegerL 2)) 

Ben TH ekleme f neye benzediğini görmek için runQ kullanmaya teşebbüs burada yaptık neler veya örnek koddaki tüm işlevlerim. baz ve bez başarısız olur, ancak boz ve byz için çalışır. byz sadece (VarE Main.g cinsinden) adıyla g atıfta iken, boz temelde sadece ismen + bahsediyor (VarE GHC.Num.+ cinsinden):

, biz fonksiyonlar kaldırılır nasıl görebilirsiniz boz ve byz için TH bakarak. baz ve bez için

bu seçenek masada değil: o fonksiyonların hem yerel bağlı olan f splice çalışıyorsunuz; bu nedenle, VarE f referansı, baz ve bez dışında anlam ifade etmez.

Peki bir geliştirici ne yapmalı? Kısacası, [| f |]'u denemek yerine, ekleme işleminin gerçekleştiği yere bağlı olacak tanımlayıcılar açısından, asansörde f ifadesini doğrudan yazmanız gerekir.

Bir yan notda, global olarak tanımlanan işlevleri her zaman kaldırabildiğinizden dolayı, cebirsel veri türleri için Lift örneklerini yazmak çok kolaydır. Ben [dokümanlar] bulduk

instance Lift a => Lift (Maybe a) where 
    lift Nothing = [| Nothing |] 
    lift (Just a) = [| Just a |] 
+0

Teşekkürler! Bu yeni TH anlayışı ile etrafındaki şeyleri değiştirerek işler yapabildim. –

İlgili konular