私はhaskellが初めてで、intにリストのすべての要素を掛ける関数を作成しようとしています。
例:
mult 2 [2,4,6]
戻り値:
[4,8,12]
問題を概念的なステップに分解します。
関数によって提供される一般的な操作である、リストのすべての要素に対して何かをしたいとしmap
ます。それを使用すると、リストを無視して、単一の要素で何をする必要があるかだけを考慮することができます。
2 つの数値を掛け合わせたいとします。関数を 1 回使用すると、これらの数値の 1 つが定数になるため、関数の引数として名前を付けることができますmult x = ...
。これで、定数として扱うことができx
、他の数値のみを気にすることができます。
もう 1 つの数値は定数ではないため、単純な式だけでなく、関数が必要です。Haskell は、 のような中置演算子でこれを行うための「演算子セクション」を提供しているので、 get(*)
を使用します。x
(x *)
最後のいくつかの手順を取り消してx
、名前を付けて関数を作成します。これを関数に渡します。map
mult x = map (x *)
...そして、あなたがしたいのであれば、あなたは実際にこの時点で終わっています。しかし、初心者にとっては、リストを明示的な引数にする方が明確かもしれません:
mult x ys = map (x *) ys
ただし、どちらの形式でも同じことを行います。
私は最初、やや否定的なゴルフ スタイルでこれに答えたので、もう一度試してみましょう。私の意図は 2 つあります: 新参者への気高い睡眠不足の回答を書いたことで自分自身を償還すること、:-)、ポイントの自由なスタイルをほのめかそうとすること:
mult_l = map . (*)
そのコードは何をしますか?
パイプライン化された方法で考えると役に立ちます。
そのコードはそれを受け取り(*)
、にフィードしますmap
。
の型は(*)
何ですか? そうですねNum a => a -> a -> a
。これは何をすることを意味しますか?数値を受け取り ( と呼びますx
)、別の関数を提供します。この関数は、別の数値を指定すると ( と呼びます)、 "times"y
を計算します。(型クラスなので、「回」を括弧に入れます...)x
y
Num
で作曲 (*)
しますmap
。何をしmap
ますか?それでは、その型を見てみましょう: (a -> b) -> [a] -> [b]
. したがってmap
、関数を引数として取り、その関数をリストの各メンバーに適用します。
合成がどのように機能するかを考えてみましょう(f . g) x = f (g x)
。
引数が与えられた場合は、2 と言います。
mult_l 2
本当に
(map . (*)) 2
これは本当にただです:
map (* 2)
ここで、map
2 つの引数を取り、関数 (「何をしてほしいですか?」) とリスト (「何をしてほしいですか?」) を受け取ります。 map
次に、そのリスト内の各項目を取得し、関数を要素に点ごとに適用します。
これは、次のようなものを取る場合を意味します。
map (* 2) [1,2,3]
次に、 map はリストを取得し、最初の要素を見て、それを 2 倍し、2 番目の要素を調べます...
したがって、 の型はmap . (*)
ですNum a => a -> [a] -> [a]
。これは、数値を受け取り、x
高階関数\x -> (* x)
を にフィードするためですmap
。
さて、あなたへの挑戦的な質問は (あなたは Haskell の初心者なので)、 how to write map
? です。ヒントをあげます:
これから、 の再帰的な定義map
と、関連する誘導原理が得られます。
map . (*)
あなたが困惑するかもしれないもう1つのことは、なぜ私はmap (*)
. 少し考えてみると、ポイントフリースタイルに少しだけ悟りが開けるかもしれません
リスト内包表記について誰も話さなかったので、それを行う別の方法について説明します。
mult x ys = [i*x | i <- ys]