Tôi đang viết trình tạo mã có đầu ra phụ thuộc vào mô tả trường dữ liệu được lưu trữ trong các phiên bản lớp của chúng. Tuy nhiên, tôi không thể tìm thấy cách chạy một hàm với đối số được tạo ra TH.Làm thế nào để vượt qua giới hạn giai đoạn GHC?
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
module Generator where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
data Description = Description String [Description] deriving Show
class HasDescription a where
getDescription :: a -> Description
instance HasDescription Int where
getDescription _ = Description "Int" []
instance (HasDescription a, HasDescription b) => HasDescription (a, b) where
getDescription (_ :: (a, b)) = Description "Tuple2" [getDescription (undefined :: a), getDescription (undefined :: b)]
-- | creates instance of HasDescription for the passed datatype changing descriptions of its fields
mkHasDescription :: Name -> Q [Dec]
mkHasDescription dName = do
reify dName >>= runIO . print
TyConI (DataD cxt name tyVarBndr [NormalC cName types] derives) <- reify dName
-- Attempt to get description of data to modify it.
let mkSubDesc t = let Description desc ds = getDescription (undefined :: $(return t)) in [| Description $(lift $ desC++ "Modified") $(lift ds) |]
let body = [| Description $(lift $ nameBase dName) $(listE $ map (mkSubDesc . snd) types) |]
getDescription' <- funD 'getDescription [clause [wildP] (normalB body) []]
return [ InstanceD [] (AppT (ConT ''HasDescription) (ConT dName)) [getDescription'] ]
Khi mô-đun khác cố gắng sử dụng Generator
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
import Generator
data MyData = MyData Int Int
mkHasDescription ''MyData
{- the code I want to generate
instance HasDescription MyData where
getDescription _ = Description "MyData" [Description "IntModified" [], Description "IntModified" []]
-}
dường như một lỗi
Generator.hs:23:85:
GHC stage restriction: `t'
is used in a top-level splice or annotation,
and must be imported, not defined locally
In the first argument of `return', namely `t'
In the expression: return t
In an expression type signature: $(return t)
chỉnh sửa:
Khi yêu cầu tôi nghĩ rằng vấn đề này xuất hiện chỉ vì tôi chỉ đã không nắm bắt một cái gì đó rất quan trọng trong TH và nó có thể được giải quyết bằng cách di chuyển một số chức năng đến các mô-đun khác.
Nếu không thể tạo dữ liệu được xác định trước như ví dụ từ câu hỏi, tôi muốn tìm hiểu thêm về các hạn chế về lý thuyết của TH.
Tôi thấy rằng ... đáng ngạc nhiên, điều đó sẽ không hoạt động. Có lẽ bạn cũng cần bật QuasiQuotes? –