4

私には2つの機能があります:

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    

まず、2 つの文字列から Map を作成します。2 つ目は、ランダム マップを生成します。最初のものは Map.Map Char Char を返します。2 つ目は IO (Map.Map Char Char) を返します

ここで、このマップから値を検索する必要があり、IO マップ用とマップ用の 2 つの関数を作成しました。

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

コードの重複を引き起こすので、私はそれが好きではありません。既に 1 つの関数を複製しています。この方法でコーディングすると、すべての関数を複製する必要があります。

Map と IO (Map) で同じように機能する関数を作成する方法はありますか?

4

2 に答える 2

8

do-notation、または脱糖する「バインド」演算子>>=がこれを処理します。

を呼び出したところならどこでもtranslate_char_io、モナド構文でテーブルをアンラップできるようにすることで、純粋関数の呼び出しを使用できます。たとえば、ランダム テーブルを作成し、その中で 2 つの異なる文字を検索する場合は、次のようにすることができます。

test c1 c2 = do
    table <- random_trans_table
    return (translate_char table c1, translate_char table c2)
于 2012-11-01T06:03:00.837 に答える
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 記法を使用して IO コードで純粋な関数を使用することもできます。この場合はおそらく最も簡単です。

translateAndPrint = do
    table <- random_trans_table
    char <- getChar
    putChar (translate_char table char)
于 2012-11-01T06:13:44.467 に答える