Avoiding duplication of functions (IO and non-IO versions)

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 

The first of these creates a two-line map; the second generates a random card. The first returns Map.Map Char Char; the second returns IO (Map.Map Char Char)

Now I need to look up the value from this Card, and I created two functions: one for the I / O card and one for the card:

 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 this because it causes code duplication. I already duplicate one function, and if I code in this way, I will need to duplicate all my functions.

Is there a way to create a function that will work with Map and IO (Map) the same way?

+4
source share
2 answers

do notation or the binding operator >>= , which it disables, takes care of this for you.

Anywhere you would call translate_char_io , you can use a pure function call, letting the monad syntax expand your table for you. For example, if you want to create a random table and find two different characters in it, you can do it like this:

 test c1 c2 = do table <- random_trans_table return (translate_char table c1, translate_char table c2) 
+8
source

You can use liftM ( import Control.Monad ) to write the converter:

 translate_char_io table c = liftM (\table' -> translate_char table' c) table 

Notice why you only need the table argument IO , but this is an option. liftM (translate_char c) table arguments, you can only get rid of the internal function for the liftM (translate_char c) table . If you want both arguments to be executed 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 the IO code, which is probably the easiest thing to do in this case:

 translateAndPrint = do table <- random_trans_table char <- getChar putChar (translate_char table char) 
+4
source

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


All Articles