169 похожих чатов

Спрашивал уже это пол года назад примерно в новичковом чате,

но теперь уже продвинулся по Хаскелю и думаю, может есть у этой задачи более красивые "продвинутые решения". Нужно распарсить список опций, которые идут в произвольном порядке. Для каждой опции есть свой парсер и свой тип. Совсем простое решение в таком стиле
unOrd2 :: Alternative f => f a -> f b -> f (a, b)
unOrd2 fa fb = asum
[ (\a b -> (a, b)) <$> fa <*> fb,
(\b a -> (a, b)) <$> fb <*> fa
]

unOrd3 :: Alternative f => f a -> f b -> f c -> f (a, b, c)
unOrd3 fa fb fc = asum
[ (\a (b, c) -> (a, b, c)) <$> fa <*> unOrd2 fb fc,
(\b (a, c) -> (a, b, c)) <$> fb <*> unOrd2 fa fc,
(\c (a, b) -> (a, b, c)) <$> fc <*> unOrd2 fa fb
]

parseTest (unOrd2 pA pB) "ba" -- (a, b)
parseTest (unOrd3 pA pC pB) "abc" -- (a, c, b)
parseTest (unOrd3 pA pC pB) "ab" -- expected 'c'
parseTest (unOrd3 pA (optional pC) pB) "ab" -- (a, Nothing, b)
parseTest (unOrd3 pA (optional pC) pB) "cab" -- (a, Just c, b)
сначала мне не очень показалось, так как нужно этих unOrd кучу написать.
На данный момент у меня это работает через парсер списка: сначала опции парсятся "грубым" парсером, который только понимает, где одна закончилась и новая началась, а затем уже на списке строк вызываются парсеры самих опций. Использование выглядит примерно так:
do -- in Parsec monad
(a, b, c) <- pOpt $ do
-- in OptParser monad
a <- mkOptP pA
b <- mkOptP pB
c <- mkOptP pC
return (a, b, c)
Выглядит, может, и не сильно проще, чем с unOrd-функциями, но более привычно как-то. Но есть проблемы:
1) Сейчас опции стали более сложные и не получается разделить их не распарсив, соответственно в список сложить не получится
2) Приходится играть со стейтом MegaParsec'a, чтобы правильные позиции ошибок внутренних парсеров выдавать

В связи с этим хотелось бы поступить наоборот: сложить парсеры в список и выбирать (альтернативой) первый подошедший, затем его откладывать вместе с результатом и смотреть оставшееся. Можно ли как-то это сделать через HList или что-то типа того?

9 ответов

21 просмотр

optparse-applicative не предлагать?

Лев-Дворкин Автор вопроса
IC Rainbow
optparse-applicative не предлагать?

мне нужно внутри MegaParsec'a это запустить как-то И optparse разве не делит всё в список сначала?

Лев-Дворкин Автор вопроса
Лев Дворкин
мне нужно внутри MegaParsec'a это запустить как-то...

а, нет, извиняюсь почему-то не додумался, что надо в код optparse сначала посмотреть может быть и действительно подобное решение сработает

Извините, не удержался (\a b -> (a, b)) <$> fa <*> fb ---> liftA2 (,) fa fb

Лев-Дворкин Автор вопроса
Kirill Valyavin
Извините, не удержался (\a b -> (a, b)) <$> fa <*>...

да, это я, конечно, понимаю :) просто тут суть в том, чтоб как можно единообразнее было написать, чтобы проще было искать общее решение теперь разбираюсь с GADT в optparse-applicative может быть и получится даже то, что хочется

Лев-Дворкин Автор вопроса
Kirill Valyavin
А где нарушилась бы единообразность?

в функциях unOrd. Но это вообще неважно, так как я это специально для примера только набрал

Не уверен что нужно, но можно data PartNP f xs = forall y ys . PartNP (f y) (NP f ys) (forall g . g y -> NP g ys -> NP g xs) parts :: NP f xs -> [PartNP f xs] parts Nil = [] parts (x :* xs) = PartNP x xs (:*):fmap (\(PartNP y ys inj) -> PartNP y (x :* ys) \p (q :* qs) -> q :* inj p qs) (parts xs) unordered :: Alternative f => NP f xs -> f (NP I xs) unordered Nil = pure Nil unordered xs = asum $ parts xs <&> \(PartNP y ys inj) -> liftA2 (inj . I) y (unordered ys) test :: Parsec Void Text (NP I [Text, Text, Int, [Double]]) test = unordered $ "foo" :* "bar" :* decimal :* between "[" "]" (float `sepEndBy` ",") :* Nil   ordNub $ parseMaybe (test <* eof) . mconcat <$> permutations ["foo", "bar", "42", "[12.34,56.78]"] [Just (I "foo" :* I "bar" :* I 42 :* I [12.34,56.78] :* Nil)] Но про перформанс этого мне конечно даже думать страшно

Какой пример для 1)?

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
1
Он в одиночку это дело запилил или была какая-то команда?
Aquinary
12
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Всем привет, нужна как никогда, нужна помощь с IO в загрузчике. Пишу в code16 после установки сегментных регистров, пишу вывод символа. Пробовал 2 варианта: # 1 mov $0x0E, %a...
Shadow Akira
14
Карта сайта