我有两个功能:
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
首先从两个字符串创建Map;第二个生成随机地图。 第一个返回Map.Map Char Char;第二个返回IO(Map.Map Char Char)
现在我需要从这个Map中查找值,我创建了两个函数 - 一个用于IO Map,另一个用于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
我不喜欢它,因为它会导致代码重复。我已经复制了一个函数,如果我通过这种方式编码,我将需要复制我的所有函数。
有没有办法创建与Map和IO(Map)一样的函数?
答案 0 :(得分:8)
do
- 符号,或者它所取消的“绑定”运算符>>=
,为您处理此问题。
你可以调用translate_char_io
的任何地方,你可以通过让monad语法为你打开你的表来调用纯函数。例如,如果您想创建一个随机表并在其中查找两个不同的字符,您可以这样做:
test c1 c2 = do
table <- random_trans_table
return (translate_char table c1, translate_char table c2)
答案 1 :(得分:4)
您可以使用liftM(import Control.Monad
)来编写转换器:
translate_char_io table c = liftM (\table' -> translate_char table' c) table
请注意,为什么您只希望table
参数为IO
,但这是一个选项。翻转参数可以让你摆脱liftM (translate_char c) table
的内部函数。如果您希望两个参数都作为IO
操作,您也可以使用liftM2
:
translate_get_char = liftM2 translate_char random_trans_table getChar
或者您可以使用do-notation在IO代码中使用纯函数,在这种情况下这可能是最简单的:
translateAndPrint = do
table <- random_trans_table
char <- getChar
putChar (translate_char table char)