Для чего нужен параметр типа во внутренних компонентах построителя байтовых строк?

Основные типы данных Data.ByteString.Builder:

newtype Builder = Builder (forall r. BuildStep r -> BuildStep r)

type BuildStep a = BufferRange -> IO (BuildSignal a)

data BuildSignal a =
    Done {-# UNPACK #-} !(Ptr Word8) a
  | BufferFull
      {-# UNPACK #-} !Int 
      {-# UNPACK #-} !(Ptr Word8)
                     (BuildStep a)
  | InsertChunk
      {-# UNPACK #-} !(Ptr Word8)
                     S.ByteString
                     (BuildStep a)

Какой цели служит параметр типа (r или a)?


person sjakobi    schedule 04.04.2018    source источник
comment
Я подозреваю, что это похоже на фантомный параметр в ST — он не позволяет вам использовать указатели в контексте, где данные не существуют.   -  person leftaroundabout    schedule 04.04.2018
comment
@leftaroundabout Не похоже на параметр фантомного типа, поскольку в конструкторе Done есть поле с типом a.   -  person Shersh    schedule 04.04.2018
comment
@leftaroundabout Можете ли вы расширить эту функциональность с помощью ST или у вас может быть ссылка?   -  person sjakobi    schedule 05.04.2018
comment
@sjakobi the ST монада имеет дополнительный параметр s, который на самом деле ни для чего не используется. Система типов гарантирует, что этот параметр «синхронизируется» с любым заданным изменяемым вычислением. Чтобы получить какой-либо результат из такого вычисления, вам нужно использовать runST, чей тип Rank-2 не позволяет вам привязать s к чему-либо конкретному. Так что, если вы тайком вытащите ссылку, например, на изменяемый массив из такого вычисления, вы можете сделать с ним в другом месте, потому что тип s не соответствует.   -  person leftaroundabout    schedule 05.04.2018


Ответы (2)


В этом нет необходимости. В качестве доказательства я создал ответвление, которое не меняет ни один из общедоступных API-интерфейсов. только API модулей с именем Internal, но удаляет этот аргумент типа.

person Daniel Wagner    schedule 04.04.2018
comment
Вы случайно не знаете, на что похожа политика совместимости bytestring для модулей Internal? Я знаю, например, что attoparsec действительно роется во внутренностях bytestring (example), поэтому, нравится вам это или нет, изменение внутренних API может привести к нарушению нижестоящих зависимостей. Я предполагаю, что сопровождающие bytestring могли бы согласиться на такой PR с большим скачком оборотов... - person Benjamin Hodgson♦; 04.04.2018
comment
Спасибо за ваше расследование, @daniel-wagner! Я заметил, что оригинал Саймона Мейера design не имеет аргументов типа, но мне все еще интересно, почему они были добавлены. - person sjakobi; 04.04.2018
comment
@sjakobi Я подозреваю, что это было помещено туда как «на всякий случай»: на всякий случай, если кто-то захочет вычислить какое-то интересное, потенциально структурированное значение о ByteString во время его создания. Потом оказалось, что люди не хотели этого делать — по крайней мере, не в том коде, который сегодня есть в библиотеке. Есть ли кто-то, кто полагается на эту возможность, — вопрос, на который мы, возможно, никогда не сможем разумно ответить отрицательно. - person Daniel Wagner; 05.04.2018
comment
@Шерш Возможно. Кто-то, заинтересованный в том, чтобы превратить его в PR, вероятно, захочет быть более осторожным, вырывая только то, что больше невозможно без дополнительного параметра типа. Я выбрал изменения, которые было проще всего объединить и проверить с проверкой типа, а не минимальное изменение — и я не очень заинтересован в выполнении работы, которая, вероятно, необходима для перехода патча от проверки концепции к приемлемому для строки байтов. сопровождающие. Конечно, если вас это волнует, вы можете сделать это сами. - person Daniel Wagner; 05.04.2018
comment
Что ж, как я уже говорил, целью этого параметра может быть просто предотвращение компиляции некоторого (неправильного) кода, а не выполнение каких-либо действий для корректного кода. - person leftaroundabout; 05.04.2018
comment
@leftaroundabout Он недостаточно полиморфен для этой роли. (Я проверил это мысленно во время рефакторинга.) - person Daniel Wagner; 05.04.2018
comment
@Shersh: я создал github.com/haskell/bytestring/issues/154 для сейчас. - person sjakobi; 06.04.2018

Саймон Мейер, автор этого Builder дизайна, ответил на мой вопрос в трекере bytestring:

Параметр типа должен был поддерживать монаду Put (специализированная Writer для заполнения буфера во время вычисления его значения).

Put определяется как

newtype Put a = Put { unPut :: forall r. (a -> BuildStep r) -> BuildStep r }

и экспортируется из Data.ByteString.Builder.Internal, который скрыт в текущей версии bytestring.

person sjakobi    schedule 25.02.2019