给定记录(不是记录的实例,记录定义本身),例如:
data Request
= Expand { shortUrl :: [String]
, hash :: [String]
}
| Shorten { longUrl :: String
, domain :: String
}
| LinkEdit { link :: String
, title :: Maybe String
, note :: Maybe String
, private :: Maybe Bool
, user_ts :: Maybe Int
, archived :: Maybe Bool
, edit :: [String]
}
如何使用记录定义中的信息生成代码 - 例如:
mkReqUrl :: Request -> String
mkReqUrl (Expand shortUrl hash) = mru "expand" (zr "shortUrl" [shortUrl] ++ zr "hash" [hash])
mkReqUrl (Shorten longUrl domain) = mru "shorten" (zr "longUrl" [longUrl] ++ zr "domain" [domain])
...
我想象一下TemplateHaskell和一个泛型库(例如,Uniplate)的一些用法可能会成功。 (我已达到顶峰 镜头实现,因为它处理记录定义,但我迷失在代码中。)。
答案 0 :(得分:3)
GHC.Generics(实际上,GHC 7.8附带的版本的文档可能是更好的阅读;见下文)可能是现在这样做的方法。首先为您的类型派生Generic
个实例:
{-# LANGUAGE DeriveGeneric #-}
data Request = ...
deriving Generic
然后,您可以使用from
将您的值转换为其通用表示类型,并将selName
应用于该结构的相应部分(S1 Blah_blah Foo...
位之一)。
我会把最后一部分作为练习留给你; Rep
类型的结构是超级拜占庭式的。虽然看起来它在新的GHC here中已有详细记录。
答案 1 :(得分:0)
如何使用模板Haskell进行身份验证
(以下内容经过手工编辑,便于阅读)
> ghci -XTemplateHaskell
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
...
Prelude> :m + Language.Haskell.TH
Prelude Language.Haskell.TH> :{
data Request
= Expand { shortUrl :: [String]
, hash :: [String]
}
| Shorten { longUrl :: String
, domain :: String
}
| LinkEdit { link :: String
, title :: Maybe String
, note :: Maybe String
, private :: Maybe Bool
, user_ts :: Maybe Int
, archived :: Maybe Bool
, edit :: [String]
}
Prelude Language.Haskell.TH| :}
Prelude Language.Haskell.TH> $(stringE . show =<< reify ''Request)
...
"TyConI (DataD [] :Interactive.Request []
[RecC :Interactive.Expand [(:Interactive.shortUrl,NotStrict,AppT ListT (ConT GHC.Base.String))
,(:Interactive.hash,NotStrict,AppT ListT (ConT GHC.Base.String))]
,RecC :Interactive.Shorten [(:Interactive.longUrl,NotStrict,ConT GHC.Base.String)
,(:Interactive.domain,NotStrict,ConT GHC.Base.String)]
,RecC :Interactive.LinkEdit [(:Interactive.link,NotStrict,ConT GHC.Base.String)
,(:Interactive.title,NotStrict,AppT (ConT Data.Maybe.Maybe) (ConT GHC.Base.String))
,(:Interactive.note,NotStrict,AppT (ConT Data.Maybe.Maybe) (ConT GHC.Base.String))
,(:Interactive.private,NotStrict,AppT (ConT Data.Maybe.Maybe) (ConT GHC.Types.Bool))
,(:Interactive.user_ts,NotStrict,AppT (ConT Data.Maybe.Maybe) (ConT GHC.Types.Int))
,(:Interactive.archived,NotStrict,AppT (ConT Data.Maybe.Maybe) (ConT GHC.Types.Bool))
,(:Interactive.edit,NotStrict,AppT ListT (ConT GHC.Base.String))]]
[])"
然后可以使用标准递归/模式匹配来遍历从reify
返回的结构。