[英]How do you reify/walk a record definition in Haskell
給定一條記錄(不是記錄的實例,而是記錄定義本身),例如:
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)來解決問題。 (由於它處理記錄定義,所以我在Lens實現方面達到了頂峰,但是我迷失了代碼。)
GHC.Generics (實際上,GHC 7.8附帶的版本的文檔可能更好閱讀;請參閱下文)可能是現在執行此操作的方法。 首先為您的類型派生一個Generic
實例:
{-# LANGUAGE DeriveGeneric #-}
data Request = ...
deriving Generic
然后,您可以使用from
將值轉換為其通用表示類型,並將selName
應用於該結構的適當部分( S1 Blah_blah Foo...
位之一)。
我將最后一部分留給您練習。 Rep
類型的結構是超級拜占庭式。 盡管看起來它將在此處的新GHC中得到充分記錄。
如何使用模板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
返回的結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.