2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение21.01.2015, 02:31 
Заслуженный участник


27/04/09
28128
_Ivana в сообщении #965954 писал(а):
MonadPlus буду кусать после Monad. Сейчас хочу запаковать
Код:
f l == True = Nothing
чтобы остальные строки нижней функции без ифов написать.

Не понял этот кусок кода. :?

Если про if null li then Nothing else Just $ f $ head li $ tail li, тут явно уместно написать функцию и превратить этот кусок в придуматьИмя li f, как считаете?

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение21.01.2015, 02:34 


05/09/12
2587
Нет смысла логику из кейса выносить далеко. Я написал свой костыль для этого дела -
Код:
tst
, применяю его для монады Мэйби в трех местах внутри кода:
код: [ скачать ] [ спрятать ]
Используется синтаксис Haskell
parseRegExp :: String -> Maybe RegExp
parseRegExp s  = go s nl where

    nl = Just []

    packlist []  = Nothing
    packlist [a] = Just $ a
    packlist  l  = Just $ Str $ reverse l

    tst r
        | r         = Nothing
        | otherwise = Just undefined

    spanclose s = tst (null w) >> Just (init l, drop (length l) s) where
        w = filter ((==(-1)).sum.map f).inits $ s
        l = head w
        f '(' = 1
        f ')' = -1
        f  _  = 0

    go _       Nothing = Nothing
    go []     (Just l) = packlist l
    go (c:cs) (Just l) = case c of
        '(' -> spanclose cs >>= \(sl,sr) -> go sr $ go sl nl >>= Just.(:l)
        '|' -> packlist l >>= \pl -> go cs nl >>= \pr -> Just $ Or pl pr
        '*' -> tst (null l) >> (go cs $ Just $ ZeroOrMore (head l) : (tail l))
        '.' -> go cs $ Just $ BAny : l
        _   -> tst (not $ isAlpha c) >> (go cs $ Just $ Normal c : l)


-- 21.01.2015, 02:45 --

У меня в каждом (почти) кейсе разбора очередного символа может произойти неудача разбора и надо вернуть Nothing - удобно это делать по одному паттерну - только что освоенному мною монаде Мэйби. Но тогда и входящие условия надо переводить в Nothing при неудаче - для этого и костыль tst :) По-моему логика приобретает стройность даже на костыле :)

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение21.01.2015, 14:28 
Заслуженный участник
Аватара пользователя


06/10/08
6422
_Ivana в сообщении #965957 писал(а):
Но тогда и входящие условия надо переводить в Nothing при неудаче - для этого и костыль tst :) По-моему логика приобретает стройность даже на костыле :)
Есть функция guard, которая для Maybe делает то, что нужно. Ее можно найти, поиском по типу: https://www.haskell.org/hoogle/?hoogle= ... ybe+%28%29

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение21.01.2015, 23:00 


05/09/12
2587
Xaositect Спасибо, именно оно. И mzero = Nothing для Maybe очень кстати. Переписал в do - нотации, получилось немножко читабельнее за счет ухода от лямбда-функций.

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение22.01.2015, 02:43 


05/09/12
2587
Упаковал кота немного, с гардами и в бездушном стиле :-) Не нравится как реализация трех моментов, каждый из которых связан со сравнением с образцом и попыткой как-то разветвить логику внутримонадных вычислений
Используется синтаксис Haskell
parseRegExp :: String -> Maybe RegExp
parseRegExp s = go s (Just []) where
    packlst l = guard (l/=[]) >> Just (r l) where r [a] = a; r a = Str $ reverse a
    substr    = find ((==1).sum.map f).inits where f ')' = 1; f '(' = -1; f _ = 0
    go s ml   = ml >>= \l -> if s=="" then packlst l else let (c:cs) = s in case c of
         '(' -> substr cs >>= \sl -> go (cs\\sl) $ go (init sl) (Just []) >>= Just.(:l)
         '|' -> packlst l >>= \pl -> go cs (Just []) >>= \pr -> Just $ Or pl pr
         '*' -> guard (l/=[])     >> go cs (Just $ ZeroOrMore h : t) where (h:t) = l
         '.' ->                      go cs (Just $ Any : l)
         _   -> guard (isAlpha c) >> go cs (Just $ Normal c : l)
 

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение22.01.2015, 03:20 
Заслуженный участник
Аватара пользователя


06/10/08
6422
Ну например, можно переписать вот этот кусок
_Ivana в сообщении #966573 писал(а):
Используется синтаксис Haskell
if s=="" then packlst l else let (c:cs) = s in case c of
         '(' -> ...
         '|' -> ...
         '*' -> ...
         '.' -> ...
         _   -> ...

как
Используется синтаксис Haskell
case s of
         "" -> packlst l
         '(':cs -> ...
         '|':cs -> ...
         '*':cs -> ...
         '.':cs -> ...
         c:cs   -> ...

 Профиль  
                  
 
 Re: Парсинг регулярных выражений на Haskell
Сообщение22.01.2015, 03:29 


05/09/12
2587
В вариантах кейса работает полноценное сопоставление с образцом? А я даже не подумал про это после кейсов в Си. Спасибо, красивее получается действительно.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: mihaild


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group