Список и оператор cons (:)
очень распространены в Haskell. Минусы - наш друг. Но иногда я хочу вместо этого добавить в конец списка.
xs `append` x = xs ++ [x]
Это, к сожалению, не эффективный способ его реализации.
Я написал треугольник Паскаля в Haskell, но мне пришлось использовать антиидиому ++ [x]
:
ptri = [1] : mkptri ptri
mkptri (row:rows) = newRow : mkptri rows
where newRow = zipWith (+) row (0:row) ++ [1]
имхо, это прекрасный читаемый треугольник Паскаля и все такое, но эта антидиома меня раздражает. Может кто-нибудь мне объяснить (и, в идеале, укажите мне хороший учебник) о том, что такое идиоматическая структура данных для случаев, когда вы хотите эффективно добавить в конец? Я надеюсь на красоту, близкую к списковой, в этой структуре данных и ее методах. Или, как вариант, объясните мне, почему эта антидиома на самом деле не так уж плоха для данного случая (если вы верите, что это так).
[править] Мне больше всего нравится ответ Data.Sequence
, который действительно обладает «почти списковой красотой». Не знаю, как я отношусь к требуемой строгости операций. Всегда приветствуются дальнейшие предложения и различные идеи.
import Data.Sequence ((|>), (<|), zipWith, singleton)
import Prelude hiding (zipWith)
ptri = singleton 1 : mkptri ptri
mkptri (seq:seqs) = newRow : mkptri seqs
where newRow = zipWith (+) seq (0 <| seq) |> 1
Теперь нам просто нужно, чтобы List был классом, чтобы другие структуры могли использовать его методы, такие как zipWith
, не скрывая его от Prelude или не уточняя его. : P