Функции в Haskell ошибка-диффузное значение с плавающей в список целых чисел


Мне нужно написать функцию, которая бы 'диффузный ошибка' плавающие значения целых чисел:

errorDiffuse :: Double -> Int -> Double -> [Int]

errorDiffuse _ 0   _   = []

errorDiffuse v num err = tv : errorDiffuse v (num - 1) (err + v - fromIntegral tv)
  where tv = truncate (v + err)

Так, что, например:

errorDiffuse 1.4 10 0 => [1,1,2,1,1,2,1,2,1,1]

(т. е. функция создает список кол-во целых чисел, каждое из которых является потолок или пол в, Начиная с заданной погрешностью значение (ноль в данном случае)).

Есть ли лучший способ написания такого рода для петли? Какие функции высшего порядка, я должен думать в терминах?



217
3
задан 2 ноября 2011 в 02:11 Источник Поделиться
Комментарии
1 ответ

Сначала я хотел избавиться от зависимости Нум, так как это просто счетчик,
и вы можете использовать взять Нум на бесконечный список errorDiffuses:

errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)

Итак, мы имеем:

errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err

Тогда я думал о создании списка errorDiffusesпо-разному.
Поскольку мы пытаемся создать список, что заставляет меня думать о разворачивается,
которые вы можете найти в данных.Список:

unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

Развертка принимает функцию, которая, учитывая семени, образует следующее
значение в списке выводится вместе с новым семенем. Функция
начинается с семян intitial, и продолжает использовать те семена, добавив к
список пока эта функция не возвращает ничего.

Функция, которую мы ищем, следующие:

nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)

Наш список бесконечный, поэтому мы всегда возвращать только значение. Значение, которое выводится на каждой стадии-это телевизор, а на следующий "семя" дается ошибаться + в - fromIntegral ТВ.

Поставив вещи у нас есть:

errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err

3
ответ дан 2 ноября 2011 в 03:11 Источник Поделиться