I have two functions:
trans_table :: [Char] -> [Char] -> Map.Map Char Char
trans_table s1 s2 = Map.fromList (zip s1 s2)
random_trans_table :: IO (Map.Map Char Char)
random_trans_table = do
rawKey <- shuffle ascii
let zipped = zip ascii rawKey
let map = Map.fromList zipped
return map
First of them creates Map from two strings; second one generates random Map. First one returns Map.Map Char Char; second one returns IO (Map.Map Char Char)
Now I need to lookup value from this Map and I have created two functions - one for IO Map and one for Map:
translate_char :: Map.Map Char Char -> Char -> Maybe Char
translate_char table c = Map.lookup c table
translate_char_io :: IO (Map.Map Char Char) -> Char -> IO (Maybe Char)
translate_char_io table c = do
raw_table <- table
let result = Map.lookup c raw_table
return result
I don't like it because it causes code duplication. I have already duplicate one function and if I code by this way I will need to duplicate all my functions.
Is there a way to create function which will works with Map and IO (Map) the same way ?
do
-notation, or the "bind" operator >>=
that it de-sugars to, takes care of this for you.
Anywhere that you would have called translate_char_io
, you can use a call to the pure function by letting the monad syntax unwrap your table for you. For example, if you want to create a random table and look up two different characters in it, you could do it this way:
test c1 c2 = do
table <- random_trans_table
return (translate_char table c1, translate_char table c2)
You can use liftM (import Control.Monad
) to write a converter:
translate_char_io table c = liftM (\table' -> translate_char table' c) table
Note sure why you'd want only the table
argument to be IO
, but it's an option. Flipping the arguments would let you get rid of the inner function for just liftM (translate_char c) table
as well. If you want both arguments to come as IO
actions, you can also use liftM2
:
translate_get_char = liftM2 translate_char random_trans_table getChar
Or you can just use do-notation to use your pure function in your IO code, which is probably easiest in this case:
translateAndPrint = do
table <- random_trans_table
char <- getChar
putChar (translate_char table char)
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