Pull to refresh

Comments 25

Xочу в субботу видеть только статьи на тему: «Что лучше: на велосипедах в лес, или на речку?»)
Спасибо, держите нас в курсе.
Спасибо за статью, у меня вот только вопрос есть: почему бы не написать просто
data BaconBox = (Tossable a) => BaconBox String a

Там действительно нужен forall a? Я, честно говоря, уже с год хаскель не трогал, подзабыл нюансы, но мне как-то интуитивно кажется, что этого должно быть достаточно, или я не прав?
Опа, разобрался сам, но тогда другой вопрос: мне кажется, или
BaconBox "bool.and" ["x", "y"] doAnd

Как-то не подходит под
data BaconBox = forall a. (Tossable a) => BaconBox String a
Упс. Это запчасти остались от рабочего кода (будущей опенсорсной библиотеки). Ещё один кусок метаданных — для превращения именованых аргументов в позиционные.
Там мало того, что нужен forall a, но ещё и {-# LANGUAGE ExistentialQuantification #-}, о чём скажет компилятор.

А нужен forall для того, чтобы задать переменную типа, на которую потом можно повесить ограничение класса (Tossable a) и использовать потом в конструкторе. Без этого будет ошибка «Not in scope: type variable `a'».
Я изначально, конечно, имел ввиду
data BaconBox a = (Tossable a) => BaconBox String a

Но тогда тип параметризированный получится, а это не то, что нужно, я понял уже.
В таком случае все методы внутри одного контейнера должны будут иметь одинаковый тип (с ограничением на Tossable).
О, сколько нам открытий чудных :-P
Одно только не понятно, тип toss:
toss :: [String] -> IO String

Но дальше по коду Вы применяете её к двум аргументам, например:
toss [] f = fmap show f

Как такое возможно?
Совершенно верно, должно быть toss :: [String] -> t -> IO String, проглядел-с.
О, сколько нам открытий чудных :-P

Я тут порылся по хакаджу и обнаружил, что реализация XMLRPC аж от 2003 года (ghc 6.8!) использует подобную технику, только вообще без коробок, а сразу же заворачивая функцию в [a] -> IO a.

Отсюда вопрос: какого ж хрена остальные продолжают клепать топорные реализации с ручным маршалингом?
Скорее всего просто не знают, что так можно. Для многих (да что уж греха таить, и для меня до недавнего времени) функции с переменным количеством аргументов в Haskell вроде printf воспринимаются как чёрная магия и нарушение законов языка. Возможно ситуация бы изменилась, если бы была какая-нибудь библиотека, реализующая эту возможность, или хотя бы популярная статья.
или хотя бы популярная статья.

А… ну вот она и есть (=
А зачем вообще BaconBox после того, как вы ввели тип Tossable? Почему не [Tossable]?

Я думал вы придумали, как совместить переменное кол-во аргументов со статическими проверками. Инструменты для этого, кстати, в принципе есть. Делая аргументы просто списком — непонятно как вы защитились от ошибок на рантайме, о которых писали в начале статьи.
> А зачем вообще BaconBox после того, как вы ввели тип Tossable? Почему не [Tossable]?

Tossable это не тип, а класс — его нельзя поместить внутрь типа, как нельзя в собаку положить будку.

> Я думал вы придумали, как совместить переменное кол-во аргументов со статическими проверками.

Как вы себе представляете статическую проверку данных из внешнего мира?..

> Делая аргументы просто списком — непонятно как вы защитились от ошибок на рантайме, о которых писали в начале статьи.

Я имел в виду ошибки самих десериализаторов, вызваные копипастой кода и невнимательностью.
Да, с Tossable я затупил :)

Статически можно хотя бы проверить количество аргументов. Чтобы программа не компилировалась, если вы передаете функции, которая принимает список из 3 аргументов, список из 2. Например с помощью типа, параметризованного type-level числом.

Это так. Но только если входные данные известны заранее и определены в коде.

Если же они прилетают из какой-нибудь IO дыры, ничего нельзя сказать наверняка. Будет такая же ошибка при конвертации из ArgList 5 Value в ArgList 3 Value
Мне кажется String в BaconBox лишний.

И конечно спасибо за статью — показана действительно интересная задача решаемая данным подходом.
Можно было конечно сделать контейнером какой-нибудь Map String BaconBox или ассоциативный список, но я решил держать метаданные метода вместе. Может пригодится для, например, автоматической генерации документации сервиса. Да и обычно методов не так много, чтобы O(n) (в худшем случае) поиск по списку был настолько прям медленней.
Удаление String из BaconBox не помешает держать метаданные с объектом — вы же можете создать тип:
data MetaData meta obj = MetaData meta obj

Оно раздельно выглядит композабельней и обобщенней.
Ваш метод идеально решает задачу превращения функции
f :: a -> b -> ... -> r

в функцию
f :: [String] -> String

И это я бы рассматривал отдельно от вашей предметной области, и вынес бы этот код в отдельный модуль.

И еще, можно не IO использовать, а просто некую монаду, и тогда изменяя ее, можно будет по разному обрабатывать ошибки, так как будет подставляться разная функция fail.
Удаление String из BaconBox не помешает держать метаданные с объектом — вы же можете создать тип:

Я ещё покручу это на реальной задаче и посмотрю как практичней будет.

И это я бы рассматривал отдельно от вашей предметной области, и вынес бы этот код в отдельный модуль.

В идеале, я бы хотел, чтобы оно могло абстрагировать протокол маршалинга и можно было бы строить частные случаи подменяя Read a, Show a, String на другие наборы. Не уверен, что такое вообще возможно, но пока я даже не задумывался о реализации — надо бы сначала частные случаи обкатать в бою.

И еще, можно не IO использовать, а просто некую монаду, и тогда изменяя ее, можно будет по разному обрабатывать ошибки, так как будет подставляться разная функция fail.


Можно и нужно. Просто конкретно в этом посте я сфокусировался на конкретном примере, чтобы можно было объяснить «на пальцах».

А так да, можно сделать (Monad m, Show a) => m a и, завернув в Identity, получить диспетчеризацию для чистых функций.
Но это не совсем то. Но и не совсем не то! awesome.gif
Тут фиксируется класс входных аргументов, гарантирующий [s]успешность[/s] наличие десерилизатора для типа

Картинки не грузятся.
Картинки не грузятся.

okay.jpg

[s]успешность[/s]

Эх… А есть чем автоматом перегнать форумную разметку в хабрахтмл?
Можно же сгенерированный форумом HTML просто взять и скопировать. Что <s>, что <del> на хабре работают. Правда если форум оформляет подчёркивание через <span style="text-decoration:underline">, то не повезло. Но все претензии к гениальным авторам форумного движка.
UFO just landed and posted this here
Sign up to leave a comment.

Articles