Синонимайзер (Haskell)

Вторник, Сентябрь 27, 2011 г.
Когда я первый раз написал синонимайзер на PyQt4, я и не подозревал, что он станет неким "Hello world" для gui приложений. Следующий вариант реализации синонимайзера был на Java. Кто дальше? Исходя из заголовка, не сложно догадаться, следующим будет — Haskell.
Haskell давно не даёт мне покоя. С того самого момента, когда он заинтересовал меня своей необычностью, я неоднократно забрасывал и вновь возвращался к постижению монад, стрелочек и прочих прелестей. Началось всё с интереса функциональному программированию в целом. Я с любопытством исследователя присматривался к достойным представителям этой парадигмы. Даже купил sicp в бумаге. Честно сказать — зацепило. Но что то мне не хватало в Scheme. Я не хочу сказать, что Lisp плох, скорее это была субъективная «не симпатия». В Haskell меня привлекла лаконичность и математическая красота исходного кода. Окрылённый чувствами я практически сразу же схватился за довольно непростую задачу обфускатор js которую так и не решил полностью. Сейчас смотрю на тот пост и многое мне не нравится. Возможно перепишу в будущем с использованием библиотеки parsec и доведу до логического конца. Но это потом, а сейчас — синонимайзер ;).
В качестве gui я решил использовать gtk и соответственно Gtk2Hs. Если вы хоть немного знакомы с haskell и когда либо ковырялись с gtk, то сложности с пониманием gtk2hs возникнуть не должно. На мой взгляд всё логично. Вот:
module Main (
    main
) where



import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.EventM
import Control.Monad.Trans ( liftIO )
import Search ( searchOut )

main ∷  IO ()
main = do
    initGUI
    window ←  windowNew
    vbox ←  vBoxNew False 10
    set window [windowDefaultWidth := 501, windowDefaultHeight := 270,
                containerBorderWidth := 10, windowTitle := "Синонимайзер",
                containerChild := vbox]
    txtInput ←  entryNew
    txtBuffer ←  textBufferNew Nothing
    txtOutput ←  textViewNewWithBuffer txtBuffer
    textViewSetWrapMode txtOutput WrapWordChar

    boxPackStart vbox txtInput PackNatural 0
    boxPackStart vbox txtOutput PackGrow 0

    onDestroy window mainQuit
    on txtInput keyPressEvent $ tryEvent $ do
        "Return" ←  eventKeyName
        liftIO $ search txtInput txtBuffer
    widgetShowAll window

    mainGUI

search ∷  Entry → TextBuffer → IO ()
search txtInput txtBuffer = do
    word ←  entryGetText txtInput
    out ←  searchOut $ word ⊕ "|"
    textBufferSetText txtBuffer out

С помощью do-нотации в функции «main» описываем интерфейс: окно, контейнер, виджеты. В 29 строке отлавливаем событие, нажатие кнопки Enter на виджете «entry». Как и в прошлые разы обойдёмся минималистичным интерфейсом без кнопки. На событие вешаем функцию «search» в качестве параметров которой передаём виджет «entry» и буфер виджета «textView». В функции «search» мы получаем результат поиска при помощи «searchOut» импортируемой из модуля «Search» в 10 строке и заносим его в буфер.
Теперь определим модуль «Search»:
module Search (
    searchOut
) where



import List ( isPrefixOf )

searchOut ∷  String → IO String
searchOut word = do
    txt ←  readFile "/path_to/sinonim"
    return $ outResult word $ searchIn word txt


searchIn ∷  String → String → [String]
searchIn word txt = filter (λx → isPrefixOf word x) lns
    where
        lns = lines txt

outResult ∷  String → [String] → String
outResult word fdesc
    | null fdesc = "нету :("
    | otherwise = desc
    where
        desc = drop len $ head fdesc
        len = length word


Использовать будем всё тот же оформленный определённым образом текстовый файл.
абитуриент|ученик,претендент,поступающий,выпускник
аблактирование|аблактировка,прививка,сращивание,прививание
аблактированный|сращенный,привитый
аблактироваться|прививаться,сращиваться
аблактируемый|прививаемый,сращиваемый
аблатив|аблятив,падеж
аблаут|абляут,чередование
абляция|унос,снос
або|альбо,ли,либо,или,аль,разве,нежто
Абов|любовь Божия
аболиция|прекращение,отмена

Тут вообще всё просто. Читаем файл, проверяем построчно наличие искомого слова в начале, далее отрезаем его и отдаём результат. Если ничего не нашли то в результате вернём «нету :(».

Вот и ещё один синонимайзер. Возможно даже не последний, ведь интересных языков так много...
Теги: guiHaskell
 
   
Комментарии (2)
Еще wxHaskell обязательно посмотрите. Код GUI приложений на нем намного более декларативен.
demoriz
27.09.2011 в 14:38
Смотрел wxWidgets ещё с Python. Он в linux использует старый GTK, который жутко смотрится :). А вот в windows вполне нормально.
Но тем не менее он вполне достоин рассмотрения. Возможно чтонить с помощью wxHaskell сделаю.
Оставить комментарий   Нажмите, чтобы отменить ответ.
Доступен html впределах разумного. Для цитирования используйте <blockquote></blockquote>, для отрисовки программного кода [code][/code].
Для всяких хакеров и прочих: комментарии проходят санитизацию, всё лишнее будет вырезано. Так что не тратьте своё драгоценное время.
Имя (обязательно)
E-Mail (Не будет опубликован , обязательно)
Сайт (необязательно)