2

モナドリストを持つ関数の構築に問題があります

 > multab 4
 ["1*1=1","1*2=2","1*3=3","1*4=4","2*2=4","2*3=6","2*4=8","3*3=9","3*4=12","4*4=16"]

だから私は次のように始めたい:

multab :: Integer -> [String]

残りについて、何か提案はありますか?

前もって感謝します。

4

4 に答える 4

8

基本的に、エントリのリストを生成してから印刷します。

エントリから始めましょう。これらは、2 つの整数とその積で構成されます。では、2 つの整数を保持する型シノニムを定義しましょう。

type Entry = (Integer, Integer)

これらの整数の積を計算する評価関数、

eval :: Entry -> Integer
eval = uncurry (*)

次に、エントリを生成する関数を定義します。

gen :: Integer -> [Entry]
gen n = [(i, j) | i <- [1 .. n], j <- [i .. n]]

例えば:

> gen 4
[(1,1),(1,2),(1,3),(1,4),(2,2),(2,3),(2,4),(3,3),(3,4),(4,4)]

次に、エントリを印刷できるようにする必要があります。

showEntry :: Entry -> String
showEntry e@(i, j) = show   i ++ "*"    ++ show j ++ "=" ++ show (eval  e)

例えば:

> showEntry (2, 3)
"2*3=6"

最後に、これらのピースを接着しましょう。

multab :: Integer -> [String]
multab = map showEntry . gen

どうぞ:

> multab 4
["1*1=1","1*2=2","1*3=3","1*4=4","2*2=4","2*3=6","2*4=8","3*3=9","3*4=12","4*4=16"]
于 2012-07-11T07:53:13.557 に答える
2

これを行う自然な方法は、 orを使用(i, j)してすべてのペアのリストを生成し、その上にマップすることです。このようなリストを生成する最も明白な方法は、次のように書くことです。これはフィルタリングを行わないため(不要なペアが生成されないため)、実行した方がよい場合があります。i <= j(\(i, j) -> show i ++ "*" ++ show j ++ "=" ++ show (i*j))[(i, j) | i <- [1..n], j <- [1..n], i <= j][1..n] >>= list where list i = map (\k -> (i, k)) [i..n]

于 2012-07-11T07:09:05.240 に答える
1

リストをモナドとして使用する他の回答の代替として。

multab :: Integer -> [String]
multab n = do
    i <- [1..n]
    j <- [i..n]
    return $ show i ++ "*" ++ show j ++ "=" ++ show (i*j)

最初の 2 つのルールは、整数のすべてのペア(i,j)j <= i <= n. 最後のルールは、出力された値を返します。

より実用的なのは、おそらくリスト内包表記バージョンです

multab2 :: Integer -> [String]
multab2 n =
    [ show i ++ "*" ++ show j ++ "=" ++ show (i*j)
    | i <- [1..n]
    , j <- [i..n] ]

これは最も効率的な変換ではありませんが、構造が示すようにモナド バージョンに直接変換できます。さらに、これは、dblhelix の回答からすべての関数をインライン化したときに得られるものと同等です。

于 2012-07-11T14:42:42.903 に答える