2

Project Eulerの質問に対する私の試みによって生成された別の質問(前の質問の続き)。次の行が理解できません。

print (maximum (map (product . take 13) (tails number)))

具体的には

map (product . take 13) (tails number)

ghci の map の最初の引数の型シグネチャは [c] -> c:

ghci> :t (product . take 13)
(product . take 13) :: Num c => [c] -> c

from ghciの型シグネチャmap (product . take 13)は [[b]] -> [b] です:

ghci> :t map (product . take 13)
map (product . take 13) :: Num b => [[b]] -> [b]

map の最初の引数は関数でなければならないので、 [[b]] はリストのリストを参照するのではなく、 によって生成された (部分的に適用された) 関数のリストを参照し(product . take 13)、2 番目の引数はから来る部分関数 (tails number)

4

2 に答える 2

3

ポイントなしのバージョンは次のとおりです。

euler8 :: (Ord c, Num c) => [c] -> c
euler8 = maximum . map (product . take 13) . tails

これをもう少しわかりやすくしましょう。

euler8' numbers = 
  let segments = tails numbers
      groups   = map (take 13) segments -- only take up to 13 numbers from each segment
      products = map product groups
      max      = maximum products
  in max

ご覧のとおり、最初に数値リストの最終セグメントを取得します(これもリストです)

次にmap、これらの各セグメントの製品を取得するために使用します (再びリスト)

最後に、それらの製品の を検索してmaximum返します

PS:print両方のバージョンで をストライプ化しました - はIO問題を複雑にするだけで、それほど重要ではないと思います...後でいつでも印刷できます ;)

于 2014-08-17T13:29:48.023 に答える
1

map の最初の引数は関数であるべきだと言っているのは正しいですか?

はい、 の最初の引数はmap関数でなければなりません。タイプを確認してください:

λ> :t map
map :: (a -> b) -> [a] -> [b]

type の関数を取ります(a -> b)。しかし、あなたの場合、は次a -> bを指します(product . take 13)

λ> :t (product . take 13)
(product . take 13) :: Num a => [a] -> a

したがって、これは要素のリストを取得し、そこから[a]型の単一の値を生成する関数aです。実際にghciでこれをテストできます:

λ> (product . take 14) [1,2,3]
6

簡単にするために、次のように適用します。

(\x -> product (take 14 x)) [1,2,3]

(tails number) から来る部分関数の 2 番目の引数は?

tails次のタイプの通常の関数です。

λ> :t tails
tails :: [a] -> [[a]]

したがって、この関数は要素のリストを受け入れ、要素のリストのリストを提供します。ghciでこれを試すことができます:

λ> tails [1,2]
[[1,2],[2],[]]

それが明確になることを願っています。

于 2014-08-17T13:46:38.440 に答える