2011-03-14 154 views
6

我需要將一個函數放入模板哈斯克爾代碼。我正在使用表達式語法:提升實例的功能?

[|f|]
某些函數似乎自動工作。然而,對於這個特殊的一個,我得到以下erroe消息:

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

我不知道如何使電梯實例功能,可似乎無法找到任何有用的信息。任何人都可以給我一個資源,或者給我一個關於這個如何實現的概念?同時我會看看是否可以削減我的具體例子。

+0

我已經找到了[文件](http://hackage.haskell.org/packages/archive/template-haskell/2.4.0.1/doc/html/Language-Haskell-TH -Syntax.html#t:電梯)(幾乎沒有)。希望它有幫助,但它可能不會:(看起來像你必須編寫一個函數'lift ::(String - > [Content]) - > Q Exp',即將你的函數翻譯成表達式。 – 2011-03-14 04:24:58

回答

7

我會採取刺,儘管如果沒有看到更多的代碼TH可能很難調試。

讓我們來看看一些示例代碼:

foo.hs:

{-# 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 |] 

現在,我們可以GHCI火這件事(我在7.0.2版本,這是什麼船與當前哈斯克爾平臺):

$ 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)) 

我在這裏所做的是試圖使用runQ看到TH拼接的外觀如F或者示例代碼中的每個函數。它在bazbez上失敗,但是適用於bozbyz

縱觀TH爲bozbyz,我們可以看到的功能是如何提升:boz基本上只是名稱引用+(在VarE GHC.Num.+),而byz只是指g的名字(在VarE Main.g)。

對於bazbez,該選項不在表格中:這兩個函數都試圖拼接f,這是局部綁定的;因此,參考VarE fbazbez之外是沒有意義的。

那麼開發人員要做什麼?簡而言之,您不需要嘗試[| f |],您需要直接在電梯中編寫f的表達式,就接頭出現時將要綁定的標識符而言。

在附註上,爲代數數據類型編寫Lift實例非常容易,因爲您始終可以提升全局定義的函數。這裏有一個Maybe

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

謝謝!通過對TH的這種新的理解,我可以改變事情的工作。 – 2011-03-14 16:10:01