一个简单的方法是定义一个数据类型的链接,即
data Link = LinkHaskell | LinkReddit
deriving (Enum, Bounded)
toUrl LinkHaskell = Url "http://www.haskell.org"
toUrl LinkReddit = Url "http://www.reddit.org"
allLinks :: [Link]
allLinks = [minBound .. maxBound]
你仍然有两个地方来指定名字,但至少现在,如果你忘了加上它的编译器会抱怨一个地方(至少有-Wall
)。
另一种方法是使用一些模板哈斯克尔法宝:
{-# LANGUAGE TemplateHaskell #-}
module Links where
import Control.Monad
import Language.Haskell.TH
data Url = Url String
deriving (Show)
mkLinks :: [(String, String)] -> Q [Dec]
mkLinks links = liftM2 (++) mkAllLinks $ mapM mkLink links
where
mkLink (name, url) = valD (varP $ mkLinkName name) (normalB [| Url url |]) []
mkAllLinks = [d| allLinks = $(listE [varE $ mkLinkName name | (name, _) <- links])|]
mkLinkName = mkName . ("link" ++)
现在你只需要指定一个地方的链接:
{-# LANGUAGE TemplateHaskell #-}
import Links
mkLinks
[("Haskell", "http://www.haskell.org")
,("Reddit", "http://www.reddit.org")
,("StackOverflow", "http://www.stackoverflow.com")
]
main = do
putStrLn "By name:"
print $ linkHaskell
print $ linkReddit
putStrLn "All:"
mapM_ print allLinks
是有可能有一个映射,其关键字是另一个数据类型? (你会为其提供数据构造函数Haskell,Reddit和Ord的一个实例)这是否会导致其他问题? – Ptival 2011-05-17 09:28:25
也许'实例枚举URL哪里...'帮助? – phynfo 2011-05-17 12:37:39