#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
]