2

Project Euler の問題を解決した後、フォーラムで次の Haskell コードを見つけました。

fillRow115 minLength = cache where
  cache = ((map fillRow115' [0 ..]) !!)
  fillRow115' 0 = 1
  fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1)

今週 Haskell の学習を始めたばかりで、このコードを理解できないようです。どなたか、次の 2 点について説明していただけないでしょうか。

  1. 私には引数が 1 つしかないように見えますminLengthが、関数を ghci で実行するには 2 つの引数が必要です。この別の議論はどこで出てくるのでしょうか?
  2. 私がオンラインで見つけることができた!! のは、リスト インデックス演算子であり、 as と呼ばれると n 番目の要素を返します[list] !! n。上記のコードは、引数を 1 つだけ指定して呼び出しているようです。それは何をしているのですか?

PS 誰かがこのコードをコピーして Project Euler の問題を解決しようと考えている場合、正しい答えが得られないようです。

4

2 に答える 2

5

この別の議論はどこで出てくるのでしょうか?

この質問をさらに単純化しましょう。あなたはおそらく関数について知っていheadます:

head [] = error "something bad"
head (x:_) = x

あなたはばかげて、単に呼び出すだけの独自の head 関数を定義することができますhead:

myHead xs = head xs

そして、左側と右側の両方が変数xsを適用していることに注意してください。これにより、eta-reduction と呼ばれるものを実行でき、結果は次のようになります。

myHead = head

型シグネチャは、次の点を強調している可能性があります。

myHead :: [a] -> a
myHead = (head :: [a] -> a)

したがって、あなたの場合、fillRow115は と等しいため、2 番目cacheの引数を取ります。これは引数を取ります。

上記のコードは、引数を 1 つだけ指定して呼び出しているようです。それは何をしているのですか?

関数を考えてみましょう+。常に 2 を加算する関数を作成する場合は、関数に 2 を「部分的に適用」できます+

addTwo  = (+2)    -- (2+) would work just as well

したがって、リストのインデックス関数を見ています!!

(!!) :: [a] -> Int -> a

そして、それは一部のリストにのみ適用されていると自分に言い聞かせます。部分適用について知っていることを適用すると、次のタイプが得られます。

(someList !!) :: Int -> a

つまり、実際には Ints からリストの要素への関数です。

これがまだクリックされないsomeList場合は、使用しているリストに置き換えてください。

someList = map fillRow115' [0..]
(someList !!) === ((map fillRow 115' [0..]) !!)
于 2013-07-04T17:37:20.243 に答える
2

この概念は と呼ばれpartial applicationます。
Haskell では、すべての関数が実際には 1 つのパラメーターしか持たないため、これが機能します。
関数は、2 つ のパラメーター (タイプ a の 1 つと型 b の 1 つ)a -> b -> cを取る関数のように見えるかもしれませんが、実際には関数です。 つまり、パラメーター (タイプ b)。http://www.haskell.org/haskellwiki/Partial_application を参照してください (または、一般的にはhttp://learnyouahaskell.com/を試してください)
a -> ( b -> c)



于 2013-07-04T17:28:12.140 に答える