Haskell находит значение сходящейся последовательности

#list #haskell #functional-programming

#Список #haskell #функциональное программирование

Вопрос:

Совершенно новый для Haskell. Я играю с последовательностью Фибоначчи, чтобы изучить основы языка, и я не могу найти идиоматический способ что-то сделать.

Последовательность Фибоначчи может быть определена следующим образом:

 fibs = 1 : 1 : zipWith ( ) fibs (tail fibs)
  

(Это уже довольно круто). Затем я хочу использовать последовательность для приближения к золотому сечению (Phi). Итак :

 ratios = zipWith (/) (tail fibs) fibs
  

это список лучших и лучших приближений Phi. Допустим, я хочу получить первое значение, когда список «стабилизировался» при заданном пороговом значении epsilon. (т. е. Разница между двумя последовательными значениями коэффициентов меньше, чем эпсилон). Я вижу, как я мог бы сделать это на императивном языке (используя индексы), но как можно было бы сделать это идиоматично в Haskell?

(Нужно ли нам использовать следующий список? Но как ?)

 diffs = zipWith (-) ratios (tail ratios)
  

Комментарии:

1. Подсказка: zip ratios diffs будет список (ratio, derivative) пар. Итак, вы захотите найти первый элемент , zip ratios diffs для которого производная ниже порогового значения.

Ответ №1:

Как? Используя другой zip . Вот однострочный вариант, основанный на том, что у вас уже есть:

 snd . head . dropWhile ((p1,p0) -> abs (p0 - p1) >= epsilon) $ zip ratio (tail ratio)
  

Читая справа налево, это говорит:

  • zip вместе список соотношений с их преемниками
  • из списка продолжайте удалять элементы, если разница между отношениями больше, чем epsilon
  • как только это будет сделано, мы берем первый элемент списка и выбираем более точный из двух.

Ответ №2:

Одной из возможностей было бы использовать понимание списка:

 getApprox threshold = head $ [ratio | (ratio, diff) <- zip (tail ratios) diffs
                                    , abs diff < threshold
                             ]