Goal of Part Two
Process Hash (Key-Value Pair) Loop by Iterating on List
This is the topic after previous section about Array (list).
Example of Doing Loop in Haskell With Map
This tutorial/ guidance/ article is one of three parts. These three combined is going to be a long article. So I won't speak too much. More on codes, than just words.
The first two parts discuss the most common loop, array in part one and hash in part two. Considering that combining map with function is tricky, This deserve this an article of its own in part three. Part three also contains comparation with other Languages, using Real World Function.
Using Tuplets as a Pair of Key and Value
Tuplets can contain many elements. Let's consider tuples contain two element below. We are going to use it as a base for our hash later.
pair :: (String, String) pair = ("key", "value")
We can use standar method
fst to access first element.
snd to access second element.
main = do print $ fst pair print $ snd pair
$ infix operator is used
to avoid parantheses (round bracket).
It is actually just
I just feel that Haskell syntax is sophisticatedly clearer.
And the result is:
Alternative Data Structure
There are other tricks to build hash dictionary, rather than use standard tuples. I suggest you to take a look at the code below to examine the possibility.
Accessing Using Pattern Matching
We can recreate our very own special function
that behave like those two standard method above.
And also get rid of the double tick quotation mark in output
In pattern matching
_, means any value.
Or just don't care about it.
key :: (String, String) -> String key (k, _) = k value :: (String, String) -> String value (_, v) = v main = do putStrLn $ key pair putStrLn $ value pair putStrLn ""
And the result is slightly different:
If you do not like the complexity,
you can wrap these two function
putStrLn $ key,
and leave the argument outside.
pair :: (String, String) pair = ("key", "value") putKeyLn :: (String, String) -> IO () putKeyLn (k, _) = do putStrLn k main = do putKeyLn pair
This will produce:
View Source File:
Let us turn our pair of associative key-value, into a more useful row of pairs. There many terminology for this, you can call it associative array, or hash, or dictionary. Consider this color scheme, that I borrow from google material color.
colorSchemes :: [(String, String)] colorSchemes = [("blue50", "#e3f2fd") ,("blue100", "#bbdefb") ,("blue200", "#90caf9") ,("blue300", "#64b5f6") ,("blue400", "#42a5f5") ,("blue500", "#2196f3") ,("blue600", "#1e88e5") ,("blue700", "#1976d2") ,("blue800", "#1565c0") ,("blue900", "#0d47a1") ]
I do not put all the google material colors. That is just a too long list to be included here.
Accessing element of hash using index, has the same syntax with previous lesson. After all it is just list of pairs.
main = do print (colorSchemes !! 2)
This will produce:
Iterate with mapM_
So is using side effect with
It is as simple as the previous example.
main = mapM_ print colorSchemes
This will produce:
("blue50","#e3f2fd") ("blue100","#bbdefb") ("blue200","#90caf9") ("blue300","#64b5f6") ("blue400","#42a5f5") ("blue500","#2196f3") ("blue600","#1e88e5") ("blue700","#1976d2") ("blue800","#1565c0") ("blue900","#0d47a1")
Iterate with map
How about producing new list with
main = do print $ map fst colorSchemes putStrLn ""
This will print raw list value. Each newly produced element is first tuples element. The key of pair.
As our need grow, we might desire to use chain functions This will accept the sequence of function as a whole compound operation.
main = do mapM_ (print . fst) colorSchemes putStrLn "" mapM_ (putStrLn . snd) colorSchemes putStrLn ""
These both map will show, raw of keys (first element), and later unquoted values (second element):
"blue50" "blue100" "blue200" "blue300" "blue400" "blue500" "blue600" "blue700" "blue800" "blue900" #e3f2fd #bbdefb #90caf9 #64b5f6 #42a5f5 #2196f3 #1e88e5 #1976d2 #1565c0 #0d47a1
Iterate Custom Function with mapM_
Furthermore as the code growing in need of more action, it is more clear to create new function. Here we have an example of an IO action procedure.
putPairLn :: (String, String) -> IO () putPairLn (key, value) = do putStrLn(key ++ " | " ++ value) main = do mapM_ putPairLn colorSchemes
This will display:
blue50 | #e3f2fd blue100 | #bbdefb blue200 | #90caf9 blue300 | #64b5f6 blue400 | #42a5f5 blue500 | #2196f3 blue600 | #1e88e5 blue700 | #1976d2 blue800 | #1565c0 blue900 | #0d47a1
Iterate Custom Function with map
And here it is, mapping function counterpart. Producing new list first as a feed to output.
pairStr :: (String, String) -> String pairStr (key, value) = key ++ " | " ++ value main = do mapM_ putStrLn (map pairStr colorSchemes) putStrLn ""
This will show the same result as above.
map seems redundant.
It is just an example required in this tutorial,
not everything have to be printed out.
Returning as IO
Many times we need to return value to IO,
we just need to
return in action
<- operator to call that action.
pairStrIO :: (String, String) -> IO String pairStrIO (key, value) = do return (key ++ " | " ++ value) main = do myPair <- pairStrIO ("myKey", "myValue") putStrLn myPair
Note that you can omit
do notation for one liner in action.
This will show:
myKey | myValue
You can use Monad directly.
If you are curious about
main = pairStrIO ("myKey", "myValue") >>= putStrLn
Or the flipped version
main = putStrLn =<< pairStrIO ("myKey", "myValue")
Iterate Custom Function with mapM
In case we need both IO side effect and list result,
we can use
main = do myMapResult <- mapM pairStrIO colorSchemes putStrLn $ show myMapResult putStrLn ""
This will produce text as below:
["blue50 | #e3f2fd","blue100 | #bbdefb","blue200 | #90caf9","blue300 | #64b5f6","blue400 | #42a5f5","blue500 | #2196f3","blue600 | #1e88e5","blue700 | #1976d2","blue800 | #1565c0","blue900 | #0d47a1"]
You might also consider using bind operator directly, as a oneliner vanilla monadic code..
main = (mapM pairStrIO colorSchemes) >>= (putStrLn . show)
Or the flipped version.
main = (putStrLn . show) =<< (mapM pairStrIO colorSchemes)
Of course, this is just a simple example on how to use
View Source File:
I hope it is clear, on how simple
for loop counterpart.
However, combining map with function is tricky. This topic deserve an article of its own.
In "Part Three" we will discuss on writing function beyond loop.