Haskell в реальной жизни

Октябрь 05, 2007, 02:32

Итак! Этот дол­го­ждан­ный мо­мент всё-таки на­сту­пил! Я по­лу­чил свой пер­вый опыт Haskell в ком­мер­че­ском про­грам­ми­ро­ва­нии!

Рас­ска­зы­ваю как дело было:

У Од­ной Боль­шой Аме­ри­кан­ской Кор­по­ра­ции есть туча про­ек­тов на­пи­сан­ный на C#/.NET Frame­work 1.1 в MS Vi­su­al Stu­dio 2003, ко­то­рые плав­но пе­ре­ко­че­ва­ли на 2005 сту­дию и FW 2.0. Всё бы ни­че­го, да вот в C# 2.0 по­яви­лось удоб­ная фича – клас­сы те­перь мо­гут быть раз­би­ты на несколь­ко фи­зи­че­ских фай­лов, со­от­вет­ствен­но весь код от­но­ся­щий­ся к ри­со­ва­нию GUI (сге­не­ри­ро­ван­ный са­мой сту­ди­ей) мож­но от­де­лить от кода как-то этим GUI управ­ля­ю­щим (на­пи­сан­ный руч­ка­ми). Ни­ка­ких стан­дарт­ных пу­тей вы­пол­нить та­кое раз­де­ле­ние для уже на­пи­сан­ных клас­сов мы не на­шли и было при­ня­то ре­ше­ние на­пи­сать Ути­ли­ту. Как са­мый боль­шой лю­би­тель де­лать что-ни­будь эда­кое, пи­сать Ути­ли­ту вы­звал­ся я.

Сра­зу ска­жу, пи­сать это на Haskell было рис­ко­ва­но с моей сто­ро­ны, всё-таки пред­сто­я­ло ис­поль­зо­вать ма­ло­зна­ко­мые ин­стру­мен­ты в ра­бо­те, ко­то­рую надо было вы­пол­нить мак­си­маль­но быст­ро, и я всё де­лал на свой страх и риск. Так что в на­ча­ле у меня немно­го по­дра­ги­ва­ли ко­лен­ки :)

Чтож, пер­вый опыт бо­е­во­го ис­поль­зо­ва­ния Haskell не толь­ко удал­ся, но и при­нес мас­су по­ло­жи­тель­ных впе­чат­ле­ний! Неко­то­рые мыс­ли и фак­ты об этом опы­те:

  • Про­ек­ти­ро­ва­ние ни­кто не от­ме­нял, вот толь­ко про­ек­ти­ро­ва­ние это функ­ци­о­наль­ное, т.к. язык чи­стый, нет ни­ка­ких шан­сов ис­поль­зо­вать на­ра­бо­тан­ный на им­пе­ра­тив­ных язы­ках опыт про­ек­ти­ро­ва­ния: клас­сов нет, пе­ре­мен­ных нет, ввод-вы­вод че­рез мо­на­ды. Эта про­грамм­ка ко­неч­но ма­лю­сень­кая, но у меня уже че­шут­ся руки на­чать на Haskell ка­кой-ни­будь Гран­ди­оз­ный Про­ект и по­смот­реть на­сколь­ко удоб­но, про­зрач­но и про­сто бу­дет вы­гля­деть его ди­зайн (или не бу­дет).
  • Для этой за­да­чи был ну­жен про­стень­кий пар­сер, мне сра­зу было по­нят­но что сред­ства­ми рег­экс­пов тут не спра­вить­ся – слиш­ком мно­го бу­дет част­ных слу­ча­ев, а глав­ное было в про­цес­се ра­бо­ты ис­ход­ные фай­лы не ис­пор­тить. Сел пи­сать пар­сер. Ясен пень что на Par­sec'е. Си­ту­а­ция слег­ка ослож­ня­лась тем, что это был пер­вый пар­сер в моей жиз­ни :) (пер­вый ра­бо­та­ю­щий и что-то де­ла­ю­щий, тео­ре­ти­че­ские зна­ния у меня кое-ка­кие ко­неч­но были). На изу­че­ние Par­sec'а (с уров­ня «несколь­ко раз смот­рел по диа­го­на­ли») и на­пи­са­ние пар­се­ра ушло 3 дня, при этом мне даже пред­ста­вить страш­но сколь­ко бы это за­ня­ло на ме­нее мощ­ных ин­стру­мен­тах – грам­ма­ти­ка у меня пол­на неод­но­знач­но­стей, весь код пар­се­ра по­крыт бло­ка­ми try, со­от­вет­ствен­но код по­лу­чил­ся тор­моз­ным, но об­ла­да­ю­щим неоспо­ри­мым пре­иму­ще­ством – он ра­бо­тал :) . Par­sec не очень по­ра­до­вал сво­ей до­ку­мен­та­ци­ей и неко­то­рой огра­ни­чен­но­стью в до­ку­мен­ти­ро­ван­ных спо­со­бах по­лу­че­ния его внут­рен­них со­сто­я­ний. Как по­лу­чить те­ку­щую по­зи­цию в виде сме­ще­ния от на­ча­ла бу­фе­ра я так и не на­шел, при­ш­лось из­вра­щать­ся с по­лу­че­ни­ем но­ме­ра стро­ки и столб­ца, а по­том уже с этим ра­бо­тать.
  • Pat­tern-match­ing ру­лит, Pat­tern-match­ing ру­лит, Pat­tern-match­ing ру­лит! :)
  • Про ле­ни­вые вы­чис­ле­ния и мо­на­ду Maybe см Pat­tern-match­ing :)
  • Ещё к во­про­су о ди­зайне: про­грам­ма пред­став­ля­ет из себя эда­кий бу­тер­брод из map-ов, fil­ter-ов и fold-ов, очень по­лез­но преду­смот­реть спо­со­бы за­лезть куда-ни­будь внутрь это­го бу­тер­бро­да, ина­че страш­но де­ла­ет­ся :)
  • Ро­ди­лась мысль так опи­сать функ­ци­о­наль­ное про­грам­ми­ро­ва­ние для лю­дей зна­ко­мых с SQL (а их очень мно­го): мы вы­пол­ня­ем за­прос, но не по таб­ли­цам, а по лю­бым дан­ным про­из­воль­ной струк­ту­ры.
  • Очень здо­ро­во ис­прав­лять ошиб­ки и вно­сить непреду­смот­рен­ные вна­ча­ле вещи: глюч­ный блок вы­ки­ну­ли, по­ста­ви­ли по­фик­шен­ный, что-ни­будь но­вень­кое в се­ре­ди­ну во­ткну­ли и ни­ка­ких про­блем. От­сут­ствие по­боч­ных эф­фек­тов в этих слу­ча­ях ру­лит неимо­вер­но.
  • Для ра­бо­ты с XML я ис­поль­зо­вал HXT. Биб­лио­те­ка мо­гу­чая и вы­зы­ва­ю­щая ува­же­ние са­мим вре­ме­нем её ком­пи­ля­ции :) . Пра­виль­ный путь ра­бо­ты с XML на HXT – это стрел­ки, я ре­шил что изу­че­ние стре­лок мо­жет за­тя­нуть­ся на неопре­де­лен­ный срок, а ко­пать мне надо быст­ро, и ис­поль­зо­вал из HXT толь­ко xread/xshow, а даль­ше как на­сто­я­щий са­му­рай руч­ка­ми раз­би­рал и из­ме­нял по­лу­чен­ное де­ре­во, этот код по­лу­чил­ся са­мым чу­до­вищ­ным.
  • Су­хие фак­ты: на всё про всё ушло 7 ра­бо­чих дней. Объ­ем ис­ход­ни­ков: пар­сер – 3 Кб, ло­ги­ка раз­ре­за­ния клас­сов на GUI и на всё осталь­ное – 8 Кб, ра­бо­та с XML, ввод-вы­вод, об­ра­бот­ка ко­манд­ной стро­ки – 3 Кб.
Да, ис­ход­ни­ки не дам, фор­маль­но они при­над­ле­жат мо­е­му ра­бо­то­да­те­лю, и чет­верть сво­ей зар­пла­ты за этот ме­сяц я по­лу­чу за про­грам­ми­ро­ва­ние на Haskell что ужас­но при­ят­но :) . Но это толь­ко пер­вая при­чи­на, вто­рая в том, что код хоть и ра­бо­чий но весь­ма страш­ный, по­это­му вы­кла­ды­вать его в учеб­ных це­лях бес­смыс­лен­но.

Одна Боль­шая Аме­ри­кан­ская Кор­по­ра­ция по­лу­чи­ла вы­пол­нен­ную ра­бо­ту и Ути­ли­ту, я по­лу­чил кучу фана, на­де­юсь что и все кто до это­го ме­ста до­чи­тал из­влек­ли для себя ка­кую-то поль­зу :)

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