Доступ к элементам списка по номеру в Hastache

Июль 12, 2012, 09:00

Это ко­неч­но очень при­ят­но ко­гда что-то по­лез­ное де­ла­ешь. Поль­зо­ва­те­лей Has­tache в мире мо­жет и не очень мно­го, но они точ­но есть. Вот недав­но Chris­ti­aan Baaij при­слал со­об­ще­ние о функ­ции ко­то­рая есть во мно­гих ре­а­ли­за­ци­ях шаб­ло­ни­за­то­ра Mus­tache, а в Has­tache нет. Это об­ра­ще­ние к эле­мен­там спис­ка по но­ме­ру, т.е. как-то так:

{{heroes.1.name}}
{{heroes.0.name}}

По­лез­ная шту­ка, мне ни разу пока не при­го­ди­лась (по­это­му и не сде­лал), од­на­ко лег­ко мож­но при­ду­мать ей при­ме­не­ние и кому-то та­кое точ­но по­на­до­бит­ся.

Поль­зо­вать­ся так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/local/bin/runhaskell
{-# LANGUAGE DeriveDataTypeable #-}
import Text.Hastache
import Text.Hastache.Context
import qualified Data.ByteString.Lazy as LZ
import Data.Data
import Data.Generics

main = mapM_ (\(template,context) ->
hastacheStr defaultConfig (encodeStr template) context >>= LZ.putStrLn)
[(template1, mkStrContext context1),
(template1, context2),
(template3, context3)]

names = ["Безымянный","Небо","Сломанный Меч","Летящий Снег","Цинь Шихуанди"]

template1 = concat [
"{{heroes.1.name}}\n",
"{{heroes.0.name}}\n"]

-- Руками написанный контекст в виде функции
context1 "heroes" = MuList $ map (mkStrContext . mkListContext) names where
mkListContext name = \"name" -> MuVariable name
context1 _ = MuNothing

-- Контекст с помощью Generics
data Hero = Hero { name :: String } deriving (Data, Typeable)
data Heroes = Heroes { heroes :: [Hero] } deriving (Data, Typeable)

context2 = mkGenericContext $ Heroes $ map Hero names

-- Контекст с помощью Generics (другой вариант)
template3 = concat [
"{{heroName.3}}\n",
"{{heroName.2}}\n"]

data HeroesStr = HeroesStr { heroName :: [String] } deriving (Data, Typeable)

context3 = mkGenericContext $ HeroesStr names

Ре­зуль­тат:

Небо
Безымянный

Небо
Безымянный

Летящий Снег
Сломанный Меч

Алгоритм Ахо-Корасик на Haskell

Март 15, 2012, 12:05

Вы­ло­жил в open source свою ре­а­ли­за­цию ал­го­рит­ма Ахо-Ко­рас­ик на Haskell. Код на GitHub. Па­кет в Hack­ageDB.

Ал­го­ритм Ахо-Ко­рас­ик — ал­го­ритм по­ис­ка под­строк, со­здан­ный Аль­фре­дом Ахо и Мар­га­рет Ко­рас­ик в 1975 году. Этот ал­го­ритм пред­на­зна­чен для од­но­вре­мен­но­го по­ис­ка сра­зу боль­шо­го ко­ли­че­ства под­строк. Ал­го­ритм со­сто­ит из двух фаз: сна­ча­ла стро­ит­ся ко­неч­ный ав­то­мат по всем под­стро­кам ко­то­рые нуж­но бу­дет ис­кать, и даль­ше че­рез этот по­стро­ен­ный ав­то­мат про­пус­ка­ет­ся текст, в ко­то­ром эти под­стро­ки нуж­но най­ти.

Моя ре­а­ли­за­ция обоб­ще­на для лю­бых по­сле­до­ва­тель­но­стей зна­че­ний, для ко­то­рых ре­а­ли­зо­ван тайп-класс Hash­able (т.е. ис­кать мож­но не толь­ко стро­ки, но и, ска­жем, по­сле­до­ва­тель­ность из чи­сел).

При­ме­ры ис­поль­зо­ва­ния

Са­мый про­стой вы­зов:

example1 = mapM_ print $ findAll simpleSM "ushers" where
simpleSM = makeSimpleStateMachine ["he","she","his","hers"]
Position {pIndex = 1, pLength = 3, pVal = "she"}
Position {pIndex = 2, pLength = 2, pVal = "he"}
Position {pIndex = 2, pLength = 4, pVal = "hers"}

К ис­ко­мым стро­кам мож­но при­вя­зать про­из­воль­ные дан­ные:

example2 = mapM_ print $ findAll sm "ushers" where
sm = makeStateMachine [("he",0),("she",1),("his",2),("hers",3)]
Position {pIndex = 1, pLength = 3, pVal = 1}
Position {pIndex = 2, pLength = 2, pVal = 0}
Position {pIndex = 2, pLength = 4, pVal = 3}

Со­здан­ный ав­то­мат мож­но за­пус­кать по ша­гам (если ну­жен по­иск не по спис­кам, а по чему-ни­будь дру­го­му):

example3 = mapM_ print $ next sm "ushers" where
sm = makeSimpleStateMachine ["he","she","his","hers"]
next _ [] = []
next sm (s:n) = let (SMStepRes match nextSM) = stateMachineStep sm s in
(s, match) : next nextSM n
('u',[])
('s',[])
('h',[])
('e',[(3,"she"),(2,"he")])
('r',[])
('s',[(4,"hers")])

Неко­то­рые по­дроб­но­сти ре­а­ли­за­ции

По­стро­е­ние ко­неч­но­го ав­то­ма­та у меня сде­ла­но в мо­на­де ST. Это мо­на­да ис­поль­зу­ет­ся, ко­гда вам нуж­ны вы­чис­ле­ния с из­ме­ня­е­мы­ми дан­ны­ми, но при этом ни­ка­кой внеш­ний мир не ну­жен (т.е. мо­на­ды IO для вас слиш­ком мно­го), со­от­вет­ствен­но сна­ру­жи мо­на­ды мы име­ем чи­стый ин­тер­фейс, а внут­ри у нас есть му­та­бель­ные пе­ре­мен­ные и мас­си­вы. Там я на­пи­сал про­стей­шую FIFO оче­редь в этой мо­на­де, мож­но по­чи­тать кому ин­те­рес­но.

Сам по­иск с ис­поль­зо­ва­ни­ем со­здан­но­го ав­то­ма­та сде­лан уже в чи­стых функ­ци­ях, это мож­но ви­деть в при­ме­рах выше.

Ссыл­ки по теме

Англоязычный генератор QR-кодов: qrcode.cx

Декабрь 13, 2011, 10:12

За­пу­стил ан­гло­языч­ную вер­сию сво­е­го ге­не­ра­то­ра QR-ко­дов: www.qr­code.cx.

До­мен­ная зона .cx при­над­ле­жит Ост­ро­ву Рож­де­ства в Ин­дий­ском оке­ане. На­се­ле­ние ост­ро­ва — 1400 че­ло­век. Пло­щадь ост­ро­ва — 135 кв. км. Луч­шей до­мен­ной зоны при­ду­мать нель­зя.

QRMania — потрясающее обновление

Ноябрь 18, 2011, 08:34

На QR­Ma­nia по­тря­са­ю­щее, неве­ро­ят­ное, вос­хи­ти­тель­ное, чу­дес­ное, сног­сши­ба­тель­ное об­нов­ле­ние! От­ныне со­зда­ние QR-ко­дов про­ис­хо­дит пря­мо у вас в бра­у­зе­ре! Ни­ка­ких об­ра­ще­ний к сер­ве­ру и пе­ре­да­чи дан­ных по Ин­тер­не­ту. Сер­вер те­перь ну­жен толь­ко для ге­не­ра­ции EPS и пред­ме­тов. В со­зда­ние обыч­но­го кода и со­хра­не­нии его в PNG-фор­ма­те сер­вер ни­как не участ­ву­ет и ваши дан­ные от вас ни­ку­да не пе­ре­да­ют­ся, ни­кем не чи­та­ют­ся и ни­ку­да не за­пи­сы­ва­ют­ся. По-мо­е­му, это за­ме­ча­тель­но.

Примеры использования Hastache

Ноябрь 14, 2011, 11:30

Вы­ло­жил при­ме­ров для has­tache: README.md (этот файл, кста­ти, хаста­шем же и со­би­ра­ет­ся — mkReadme.hs). Эти же при­ме­ры рос­сы­пью фай­лов: ex­am­ples.

Libqrencode-js: генерация QR-кодов на JavaScript

Ноябрь 14, 2011, 11:00

А вот ка­кую офи­ген­скую шту­ку я вы­ло­жил!

Это ге­не­ра­тор QR-ко­дов на чи­стом как хру­сталь JavaScript, ни­ка­ких сер­вер­ных ком­по­нен­тов, всё пря­мо в бра­у­зе­ре. Вот сра­зу де­мон­страш­ка для по­ба­ло­вать­ся.

При­чем это не абы что, это порт про­дви­ну­той C-шной биб­лио­те­ки libqren­code, ко­то­рая ра­бо­та­ет в сер­вер­ной ча­сти на по­дав­ля­ю­щем боль­шин­стве сай­тов для ге­не­ра­ции QR-ко­дов, и име­ет бин­дин­ги ко все­му на све­те. Для JavaScript уже есть ге­не­ра­то­ры QR-ко­дов, но все очень сы­рые, в от­ли­чии от libqren­code ко­то­рый уже несколь­ко лет пи­шет­ся и, как я уже го­во­рил, мно­го где ис­поль­зу­ет­ся.

Про­цесс пор­ти­ро­ва­ния C-шной биб­лио­те­ки на JavaScript, это, ска­жу я вам, про­сто пес­ня. Есть со­вер­шен­но за­ме­ча­тель­ный про­ект em­scripten — ком­пи­ля­тор LLVM в JavaScript. Вот с по­мо­щью него вол­шеб­ство и про­изо­шло. Я на­пи­сал неболь­шую C-шную оберт­ку над libqren­code, ском­пи­ли­ро­вал всё вме­сте в LLVM-код с по­мо­щью Clang, пе­ре­дал в em­scripten и на­пи­сал JavaScript оберт­ку над ре­зуль­та­том его ра­бо­ты. По­лу­чи­лось хо­ро­шо.

Ли­цен­зия LGPL (ви­ру­сом от libqren­code). Поль­зуй­тесь!

Hastache растёт и развивается

Ноябрь 08, 2011, 11:20

Но­во­сти хаста­ше­стро­е­ния:

Во-пер­вых, Akaspin при­слал по­лез­ный патч, поз­во­ля­ю­щий с по­мо­щью mk­Gener­ic­Con­text со­зда­вать кон­тек­сты для ти­пов с по­ля­ми Mona­dIO m => (Byte)String -> m (Byte)String, за что ему вы­да­ёт­ся оче­ред­ной плюс в кар­му. Сам я о та­кой воз­мож­но­сти ду­мал, но не оси­лил, ура опен­сор­су. При­мер ис­поль­зо­ва­ния тут.

Во-вто­рых, я обоб­щил кон­струк­тор Mu­Lamb­da до Mu­Var a => Mu­Lamb­da (ByteString -> a), рань­ше мож­но было толь­ко ByteString воз­вра­щать, а те­перь лю­бой тип, для ко­то­ро­го есть ин­станс клас­са Mu­Var. Удоб­но, как-то я рань­ше не со­об­ра­зил так сде­лать.

В-тре­тьих, Сам Bryan O'Sul­li­van (один из ав­то­ров кни­ги Real World Haskell), при­слал неболь­шой патч для has­tache и по­со­ве­то­вал ис­поль­зо­вать blaze-builder для за­пи­си ре­зуль­та­та ра­бо­ты шаб­ло­ни­за­то­ра. Blaze-builder пред­на­зна­чен для ге­не­ра­ции Lazy ByteString с кон­тро­лем ми­ни­маль­но­го раз­ме­ра фраг­мен­тов этой стро­ки. За счет это­го до­сти­га­ет­ся су­ще­ствен­ное уве­ли­че­ние ско­ро­сти даль­ней­шей ра­бо­ты с этой стро­кой. Вме­сто кучи мел­ких бло­ков (а имен­но так и по­лу­ча­ет­ся при ра­бо­те has­tache), име­ем несколь­ко круп­ных, ко­то­рые, к при­ме­ру, по сети уедут быст­рее (за счет ми­ни­ми­за­ции ко­ли­че­ства си­стем­ных вы­зо­вов). Так что те­перь и обыч­ный ре­зуль­тат has­tache со­сто­ит из удоб­ных круп­ных бло­ков внут­ри Lazy ByteString, и, та­к­же, мож­но по­лу­чить непо­сред­ствен­но объ­ект Builder биб­лио­те­ки blaze-builder и даль­ше уже ра­бо­тать пря­мо с ним.

«Широкий поиск» всё

Октябрь 20, 2011, 08:41

С при­скор­би­ем вы­нуж­ден со­об­щить, что Гугл по­шел по сто­пам Ян­дек­са и за­пре­тил от­кры­вать себя во фрей­мах. Судя по все­му, это про­изо­шло в рам­ках Mak­ing search more se­cure. За бо­лее без­опас­ный по­иск мож­но толь­ко по­ра­до­вать­ся, од­на­ко даль­ней­шее ис­поль­зо­ва­ние Гуг­ла в рам­ках «Ши­ро­ко­го по­ис­ка» ста­но­вит­ся тех­ни­че­ски невоз­мож­ным. Так что я буду вы­нуж­ден этот про­ект в бли­жай­шее вре­мя за­крыть, при­но­шу из­ви­не­ния всем его поль­зо­ва­те­лям.

Од­на­ко, по­сколь­ку стан­дарт­ная ор­га­ни­за­ция по­ис­ка в со­вре­мен­ных бра­у­зе­рах меня лич­но со­вер­шен­но не устра­и­ва­ет, буду ду­мать что с этим мож­но сде­лать. Сей­час у меня ос­нов­ная идея де­лать бра­у­зер­ный пла­гин. Я сам поль­зу­юсь Google Chrome, а у него весь­ма ас­ке­тич­ный API для пла­ги­нов. Бо­ко­вые па­не­ли, от ко­то­рых мож­но пля­сать с ин­тер­фей­сом по­ис­ко­во­го пла­ги­на есть пока толь­ко в экс­пе­ри­мен­таль­ном API. Вот ви­ди­мо с ними и буду раз­би­рать­ся. От двух­ко­ло­ноч­но­го по­ис­ка при­дет­ся от­ка­зать­ся, по край­ней мере до тех пор, пока не по­явит­ся API, на ко­то­ром это мож­но сде­лать. Од­на­ко, мож­но бу­дет ис­кать по всем тем сай­там, ко­то­рые за­пре­ща­ют iframe (на­при­мер stack­over­flow), а та­к­же сде­лать до­бав­ле­ние соб­ствен­ных по­ис­ко­ви­ков. Под­держ­ку Fire­fox и дру­гих бра­у­зе­ров обе­щать пока не могу, т.к. сам не поль­зу­юсь и нуж­но бу­дет смот­реть их до­ку­мен­та­цию, на­сколь­ко там всё близ­ко к Хро­му.

Cле­ди­те за ре­кла­мой. По­ста­ра­юсь вы­де­лить вре­мя на вы­ше­опи­сан­ное.

Сергей Лымарь © 2005-2014, Все права защищены.