Идиоматическое эффективное добавление Haskell?

Список и оператор 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

34
задан Chris Martin 25 April 2016 в 12:30
поделиться