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, Супермодераторы



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

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

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