I have a map data structure that has the following structure:- "What is the capital of UK"-> "London" "What is the capital of France"-> "Paris" I want to loop through this map displaying the question: "What is the capital of UK", asking for user input. If the user answers "London" I print correct, otherwise, I print the correct answer "London". This is easy in an imperative language like C# but I haven't figured how to do it in Haskell.
The issue with using Map in this manner is a lot of the traversals over Map values assume you don't care about the key and only care about the contained value. There are traversals inside Data.Map that suffice, and @danidiaz has pointed on out, but it's totally reasonable to call toList since that list will be generated lazily, not forced into memory all at once. Given a list of tuples (key, value) you can traverse that using for or mapM or fmap or .... basically any of the constructs you love so long as you can use an IO monad.
{-# LANGUAGE OverloadedLists #-}
import Data.Foldable (for_)
import Data.Map (Map,toList)
m :: Map String String
m = [("a","1"),("b","2")]
main =
for_ (toList m) $ \(q,a) ->
do putStrLn q
x <- getLine
putStrLn (if x == a
then "Yes"
else "No: " ++ a)
EDIT: I feel compelled to add what most people would call more idiomatic Haskell using mapM_:
main :: IO ()
main = mapM_ ask (toList m)
ask :: (String,String) -> IO ()
ask (q,a) = do putStrLn q
x <- getLine
putStrLn (if x == a then "Yes" else "No: " ++ a)
lens's ifor_ combinator allows you to write @ThomasM.DuBuisson's code without going via toList. The traversal function gets access to the index at each iteration.
main = ifor_ m $ \(q, a) -> do
putStrLn q
x <- getLine
putStrLn (if x == a then "Yes" else "No: " ++ a)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With