2

Haskell でループを実装することに興味があります。Haskell(疑似コード)で同様のことを行うにはどうすればよいですか:

var i = 0
for (int i1 = 0; i1 < 10; i1++) {
  println(i1)
  i += 2
}

println(i)
4

5 に答える 5

8

機能的に言​​えば、整数のリストをフォールディングして、整数ごとに要素を出力し、アキュムレータを 2 増やします。何かを出力する (つまり、I/O を行う) ため、モナドをフォールドする必要がありますが、それ以外の場合は、標準のleft-foldです。

foldM (\i i1 -> print i1 >> return (i + 2)) 0 [0..9] >>= print

コードと同じ変数名を使用するラムダ関数で折りたたみます。つまりi1、現在の要素でiあり、アキュムレータです。

i = 0次のパラメータは、コードに対応するアキュムレータの初期値です。

最後のパラメータは、(両端を含む) 折り重ねた数値のリストです。

( >>=bind 演算子) は、フォールドの結果 (つまり、 accumulator の最終値i) を print 関数にパイプします。

編集:これは、あなたが書くつもりだったと仮定しています

var i = 0
for (int i1 = 0; i1 < 10; i1++) {
  println(i1)
  i += 2
}

println(i)

ifor句とループ本体の両方でインクリメントする代わりに。

于 2013-11-04T11:04:33.480 に答える
7

という 2 つの仮定に従うと、

  1. 「似ている」とは、行動が似ていることを意味し、
  2. プリントアウトしたい方(同想定上製)

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    20
    

私はHaskellで書くだろう

do
  let xs = [0..9]
  mapM_ print xs
  print (length xs * 2)

元の計算が 3 つの別々の (そして独立した!) 計算にどのように分割されたかがわかります。

  1. ループ変数i1をリストに変換します。境界は 0 と 9 を含むことがわかっているので、ループ変数は list で表すことができます[0..9]
  2. リストの内容を出力します。これは、反復ごとにループ変数を出力するのと同じことです。
  3. iリストについて知っていることから" " を計算し、同様に出力します。

3 番目の計算は、従来の命令型プログラミングと Haskell の違いを強調しているため、特に興味深いものです。

リストの反復ごとに数値に 2 を足すことは、リストの長さを 2 倍することと同じです。私の目に大きな違いはi = length xs * 2、瞬く間にそれが何を意味するのかを読んで理解できることです. iただし、ループのすべての反復をカウントアップすることは、それが実際に何を意味するのかを理解するために少し考えなければなりません。

3 つのサブ計算がすべて独立しているという事実は、テストがはるかに簡単であることを意味します。一度に 1 つずつテストでき、個別に機能する場合は、一緒に機能することもできます。

「似ているコード」という意味で「似ている」という意味である場合は、STRef/IORef回答のいずれかを参照してください。

于 2013-11-04T11:06:46.143 に答える
1

ループを実行する簡単かつ柔軟な方法は、let または where 句で再帰関数を定義することです。

main = loop 0 10
  where
    loop i n | i < n = putStrLn (show i) >> loop (i+2) n
    loop _ _         = return ()

これは、loop2 つの変数iとの関数を定義しますn。最初のパターンには、条件 ( ) をチェックするガード( の後に) があります。true の場合、このブランチが選択され、コンソールに出力されてから、自身が再び にバインドされます。それ以外の場合は、デフォルトのブランチが選択されます。これは(= IO Monad で何もしない) だけです。|i < niloopii+2returns ()

再帰関数を使用してこのようなループを実装することは、非常に柔軟です。高階関数 ( や など) を使用するのが簡単な場合はformapループを命令型設定から変換する方法がわからない場合は、通常、再帰関数を使用するとうまくいきます。

于 2013-11-04T11:07:49.777 に答える