Композиция функций - 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],[]]
Я надеюсь, что это проясняет.