Синонимайзер (Haskell)Вторник, Сентябрь 27, 2011 г. 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
Использовать будем всё тот же оформленный определённым образом текстовый файл. абитуриент|ученик,претендент,поступающий,выпускник аблактирование|аблактировка,прививка,сращивание,прививание аблактированный|сращенный,привитый аблактироваться|прививаться,сращиваться аблактируемый|прививаемый,сращиваемый аблатив|аблятив,падеж аблаут|абляут,чередование абляция|унос,снос або|альбо,ли,либо,или,аль,разве,нежто Абов|любовь Божия аболиция|прекращение,отмена Тут вообще всё просто. Читаем файл, проверяем построчно наличие искомого слова в начале, далее отрезаем его и отдаём результат. Если ничего не нашли то в результате вернём «нету :(». Вот и ещё один синонимайзер. Возможно даже не последний, ведь интересных языков так много... | ||
Комментарии (2)
)

Но тем не менее он вполне достоин рассмотрения. Возможно чтонить с помощью wxHaskell сделаю.