خرید بک لینک

Vote count: 0

Consider the following type (in Haskell):

data CType = CInt | CDouble | CProduct String [(String, CType)]

I would like to have a function that would generate corresponding Haskell type declarations. Constructors CInt and CDouble should correspond to Int and Double types thus result in no declaration. (CProduct t ts) should correspond to the record type with name and constructor defined by t and fields defined by ts list. For example:

ty :: CType
ty = CProduct "Type1" [("proj10", CDouble), ("proj11", CProduct "Type0" [("proj0", CInt)])]

should result in two definitions:

data Type0 = Type0 {proj0 :: Int}
data Type1 = Type1 {proj10 :: Double, proj11 :: Type0} 

To define this function I use Template Haskell:

genType :: CType -> Q Type
genType CInt = retu (ConT ''Int)
genType CDouble = retu (ConT ''Double)
genType (CProduct s t) =
    do
      l <- lookupTypeName s
      case l of
        Just sn -> retu (ConT sn)
        Nothing ->
            do
              sn <- newName s
              retu (ConT sn)

genField :: (String, CType) -> Q VarStrictType
genField (s , t) =
    do
      sn <- newName s
      tn <- genType t
      retu (sn, NotStrict, tn)

genDecl :: CType -> Q [Dec]
genDecl CInt = retu []
genDecl CDouble = retu []
genDecl (CProduct s t) =
    do
      ts <- fmap join . sequence . map (genDecl . snd) $ t
      res <- lookupTypeName s
      case res of
        Just _ -> retu ts
        Nothing ->
            do
              sn <- newName s
              sc <- newName s      
              fn <- sequence . map genField $ t
              let
                  dt = DataD [] sn [] [RecC sc fn] []
              retu (dt : ts)

When I invoke the function with $(genDecl ty) for ty :: CType defined above I get following error:

The exact Name ‘Type0_adN6’ is not in scope …
      Probable cause: you used a unique Template Haskell name (NameU), 
      perhaps via newName, but did not bind it

But when I generate definitions one by one everything is fine:

$(fmap ([x, y] -> [y]) . genDecl $ ty)

$(genDecl $ ty)

So the question is: how to properly add type declarations in Q monad to generate them all at once?

asked 2 mins ago

برچسب: نویسنده: استخدام کار تاريخ: جمعه 7 خرداد 1395 ساعت: 15:17

صفحه بندی