繁体   English   中英

您如何在Haskell中验证/遍历记录定义

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM