2013-07-04 4 views
2

После решения задачи по проекту Эйлера я наткнулся на следующий код Haskell на форуме: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. Для меня это выглядит как есть только один аргумент minLength, но функция требует 2 аргумента для запуска в GHCI. Где этот другой аргумент вступает в игру?
  2. Из того, что я смог найти в Интернете, !! является оператором индекса списка и возвращает n-й элемент при вызове [list] !! n. Вышеприведенный код, по-видимому, вызывает его только с одним аргументом. Что это значит?

P.S. Если кто-то думает о копировании этого кода для решения проблемы Project Euler, он, похоже, не дает правильного ответа.

ответ

5

Где этот другой аргумент вступает в игру?

Позволяет упростить этот вопрос еще дальше. Вы, наверное, знаете о функции head:

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

Вы могли бы глупо и определить свою собственную функцию головы, которая просто вызывает head:

myHead xs = head xs 

И заметьте, как левая и правая сторона применить переменную xs, поэтому мы можем сделать так называемую эта-редукцию и привести к:

myHead = head 

Подписи типа могут забивать po ИНТ дом:

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

Так что в вашем случае, fillRow115 принимает второй аргумент, потому что она равна cache, которая принимает аргумент - и это приводит нас к вашему второму вопросу.

Этот код, по-видимому, называет его только одним аргументом. Что это значит?

Рассмотрите функцию +.Если вы хотите, чтобы сделать функцию, которая всегда добавляет 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..]) !!) 
2

Эта концепция называется partial application.
Это работает, потому что в Haskell все функции имеют только один параметр.
Функция a -> b -> c может выглядеть как функцию, которая принимает два параметра
(один из typa а, и один из типа б), но это на самом деле функция a -> (b -> c),
т.е. функция с одним В параметре (типа а), что возвращает функцию, которая принимает параметр (типа b).

См http://www.haskell.org/haskellwiki/Partial_application
(или просто в целом, дают http://learnyouahaskell.com/ идти)

Смежные вопросы