List vs Map (key security and matching of all elements)

What is the best data structure for the following scenario?

Say you have a list of URLs

linkHaskell = Url "http://www.haskell.org" linkReddit = Url "http://www.reddit.com" ... 

and you use them individually, but you also want to work with all of them, for example. link-check, you can put them in a list

 allLinks = [ linkHaskell , linkReddit ... ] 

But this is a mistake, as you may forget to add a new link.

Instead, you can save these URLs on a map, but then you will exchange compile-time errors for runtime errors if you have typos in the keys.

In Haskell, what would you do?

+6
source share
1 answer

One simple approach is to define the data type for the links, i.e.

 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] 

You still need to specify the name in two places, but at least now the compiler will complain if you forget to add it in one place (at least using -Wall ).

Another approach is to use Template Haskell magic:

 {-# 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" ++) 

Now you need to specify the links in only one place:

 {-# 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 
+5
source

Source: https://habr.com/ru/post/888298/


All Articles