haskellプログラミング学習ノート(一)高次関数
私が今日記録した学習ノートは主に3つのソースから来ています.この間haskell言語プログラミングの実践経験 を勉強しました. John BackusのCan Programming Be Liberated from the von Neumann Style?数学の基礎があまりにも弱いので、私は「読む」のではなく「読む」としか言えません.原文 を読むことを強くお勧めします. John Hughes why functional programming matters
John Backusの論文で述べた関数式プログラミングVSフォンノイマン式プログラミングはhaskellで述べた関数式プログラミングVSコマンド式プログラミングに似ている(誤読しないでほしい)
私はjavaとhaskellを用いて,この論文における内積を求める方法,すなわち,[a,b,c]と[x,y,z]を与えてsum=a*x+b*y+c*zを求めることをそれぞれ実現した.
(1)javaの実装には1つの変数を複数定義する必要がある
(2)ループ変数iは問題に存在しない(すなわちsum=a*x+b*y+c*zを求める問題にiの存在はない)
(3)John Backusの論文は,この従来のプログラミング言語のコードを頭の中で「実行」しなければその意味を理解できないと指摘している.
つまり、私たちがこのコードを読むときは、実は自分を人肉計算機として頭の中で順番に解釈して実行しています.
zipWithは関数で、zipWith f xs ysのような3つのパラメータを受け入れ、最初のパラメータfは別の関数(関数をパラメータとして渡す)であり、この関数は2つのパラメータを受け入れて1つの結果を返し、この例では(*)、つまり積である.xsとysは2つの集合(haskellではListタイプ)であり、zipWithは関数fを2つの集合の対応する要素に適用し、結果を別の集合に構成して結果とする.
sum関数は、集合の各要素を加算します.
したがって、このコードは、集合xsとysの対応する要素を乗算し、結果集合の各要素を加算することを意味します.
haskellのコードはこのコードがしたことの直感的な説明であり、haskellの書き方に慣れると、haskellコードの可読性がずっと良いことがわかります.
高次関数(すなわち関数をパラメータとして受け入れることができる)はプログラムの拡張性を大きく増大させ、
加入して積を求めたくなくて、和を求めたいのはどのように版ですか?(*)を(+)に変更し、これが最も簡単な拡張です.
もしあなたがxs集合の各要素をys集合の各要素と比較したいならば、x>yが大きいのはTrueで、さもなくばfalse、どのように実現しますか?
(>)も2つのパラメータを受け入れて、1つの結果を返す関数ですよ!
のように
why functional programming matters論文で述べたように、関数式プログラミングは言語に重要な「接着メカニズム」--高次関数を加え、小さなブロックの機能ブロックを大きな機能ブロックに組み合わせることができる.このメカニズムは非常に価値がある.
John Backusの論文で述べた関数式プログラミングVSフォンノイマン式プログラミングはhaskellで述べた関数式プログラミングVSコマンド式プログラミングに似ている(誤読しないでほしい)
私はjavaとhaskellを用いて,この論文における内積を求める方法,すなわち,[a,b,c]と[x,y,z]を与えてsum=a*x+b*y+c*zを求めることをそれぞれ実現した.
public static int innerProduct(int[] xs,int[] ys){
int sum = 0; //(1)
for ( int i=0;i<xs.length;i++){ //(2)
sum = sum + xs[i] * ys[i];
}
return sum;
} //(3)
(1)javaの実装には1つの変数を複数定義する必要がある
(2)ループ変数iは問題に存在しない(すなわちsum=a*x+b*y+c*zを求める問題にiの存在はない)
(3)John Backusの論文は,この従来のプログラミング言語のコードを頭の中で「実行」しなければその意味を理解できないと指摘している.
つまり、私たちがこのコードを読むときは、実は自分を人肉計算機として頭の中で順番に解釈して実行しています.
innerProduct :: [Int] -> [Int] -> Int
innerProduct xs ys = sum $ zipWith (*) xs ys
haskellのバージョンは典型的な関数式言語実装であり,高次関数(highorder function)の威力を示し,上述した3つの問題を回避した.zipWithは関数で、zipWith f xs ysのような3つのパラメータを受け入れ、最初のパラメータfは別の関数(関数をパラメータとして渡す)であり、この関数は2つのパラメータを受け入れて1つの結果を返し、この例では(*)、つまり積である.xsとysは2つの集合(haskellではListタイプ)であり、zipWithは関数fを2つの集合の対応する要素に適用し、結果を別の集合に構成して結果とする.
sum関数は、集合の各要素を加算します.
したがって、このコードは、集合xsとysの対応する要素を乗算し、結果集合の各要素を加算することを意味します.
haskellのコードはこのコードがしたことの直感的な説明であり、haskellの書き方に慣れると、haskellコードの可読性がずっと良いことがわかります.
高次関数(すなわち関数をパラメータとして受け入れることができる)はプログラムの拡張性を大きく増大させ、
加入して積を求めたくなくて、和を求めたいのはどのように版ですか?(*)を(+)に変更し、これが最も簡単な拡張です.
もしあなたがxs集合の各要素をys集合の各要素と比較したいならば、x>yが大きいのはTrueで、さもなくばfalse、どのように実現しますか?
(>)も2つのパラメータを受け入れて、1つの結果を返す関数ですよ!
isLarger :: [Int] -> [Int] -> [Bool]
isLarger xs ys = zipWith (>) xs ys
のように
why functional programming matters論文で述べたように、関数式プログラミングは言語に重要な「接着メカニズム」--高次関数を加え、小さなブロックの機能ブロックを大きな機能ブロックに組み合わせることができる.このメカニズムは非常に価値がある.