Композиция функций - Haskell

Опять же, еще один вопрос, вызванный моими попытками ответить на вопросы проекта Эйлера ( следуйте из предыдущего вопроса). У меня проблемы с пониманием следующей строки:

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

конкретно

map (product . take 13) (tails number)

Сигнатура типа для первого аргумента map из ghci: [c] -> c:

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

Подпись типа для map (product . take 13) из ghci есть [[b]] ​​-> [b]:

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

Прав ли я, говоря, что в качестве первого аргумента map должна быть функция, [[b]] ​​ссылается не на список списков, а на список (частично примененных) функций, сгенерированных (product . take 13) со вторым аргументом для частичных функций, поступающих из (tails number)?

2 ответа

Решение

Вот бессмысленная версия:

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 только усложнит дело, и это не очень важно... вы всегда можете распечатать его потом;)

Прав ли я, говоря, что первым аргументом map должна быть функция?

Да, первый аргумент map должен быть функцией. Видеть это тип:

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

Это принимает функцию типа (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 нормальная функция с типом:

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

Итак, эта функция принимает список элементов и выдает список элементов. Вы можете поиграть с этим в GHCI:

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

Я надеюсь, что это проясняет.

Другие вопросы по тегам