Позвольте мне объяснить, что я имею в виду с помощью чувствительной к стоимости складки с примером: вычисление pi с произвольной точностью. Мы можем использовать Leibniz formula (не очень эффективные, но хорошие и простые) и ленивые списки, как это:Срочно-зависимые складки
pi = foldr1 (+) [(fromIntegral $ 4*(-1)^i)/(fromIntegral $ 2*i+1) | i<-[0..]]
Теперь, очевидно, это вычисление никогда не будет полным, потому что мы должны вычислить все значения в бесконечном списке. Но на практике мне не нужно точное значение pi, я просто нуждаюсь в этом определенном количестве десятичных знаков. Я мог определить пи», как это:
pi' n = foldr1 (+) [(fromIntegral $ 4*(-1)^i)/(fromIntegral $ 2*i+1) | i<-[0..n]]
, но это вовсе не очевидно, что значение п мне нужно пройти, чтобы получить точность, я хочу. Мне нужна какая-то экономичная сгиб, которая перестанет складываться всякий раз, когда я получу требуемую точность. Существует ли такая складка?
(Обратите внимание, что в этом случае легко убедиться, что мы достигли требуемой точности. Поскольку формула Лейбница использует последовательность, которая чередует знак с каждым членом, ошибка всегда будет меньше абсолютного значения следующий член в последовательности.)
Редактировать: Было бы здорово иметь экономичные складки, которые могли бы также учитывать время вычисления/потребления энергии. Например, я хочу получить самое точное значение pi, учитывая, что у меня есть 1 час времени вычисления и 10kW-hrs, чтобы потратить. Но я понимаю, что это уже не будет строго функциональным.
Относительно легко определить такую складку самостоятельно, но я предполагаю, что вы спрашиваете, есть ли встроенная функция с сигнатурой что-то вроде '(a -> b -> b) -> (b -> Bool) - > [a] -> b'. – huon
@dbaupp. Определение вашей функции недостаточно, потому что '(b -> Bool)' работает только для очень ограниченного числа условий остановки. Например, если последовательность не была чередованием монотонно, тогда трюк только при просмотре следующего числа не сработает. В общем, вам, возможно, придется рассмотреть произвольное число элементов, чтобы определить, достаточно ли сходится последовательность. –
Конечно. Таким образом, более полезная сигнатура типа может быть функцией с '[b] -> Bool', а не просто' b -> Bool'? (Можно реализовать что-то близкое с 'scanl' и' dropWhile' или 'foldr'.) – huon