Имплементациjа монада у програмском jезику Swift 1.1

Σχετικά έγγραφα
Tестирање хипотеза. 5.час. 30. март Боjана Тодић Статистички софтвер март / 10

1.2. Сличност троуглова

Решења задатака са првог колоквиjума из Математике 1Б II група задатака

УНИВЕРЗИТЕТ УНИОН РАЧУНАРСКИ ФАКУЛТЕТ

b) Израз за угиб дате плоче, ако се користи само први члан реда усвојеног решења, је:

налазе се у диелектрику, релативне диелектричне константе ε r = 2, на међусобном растојању 2 a ( a =1cm

г) страница aa и пречник 2RR описаног круга правилног шестоугла јесте рац. бр. јесу самерљиве

2. Наставни колоквијум Задаци за вежбање ОЈЛЕРОВА МЕТОДА

Конструкциjе Адамарових матрица

Монте Карло Интеграциjа

1 Неодрђеност и информациjа

7. ЈЕДНОСТАВНИЈЕ КВАДРАТНЕ ДИОФАНТОВE ЈЕДНАЧИНЕ

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА МАТЕМАТИКА ТЕСТ

ПАРАЛЕЛИЗАЦИJА СТАТИЧКЕ ВЕРИФИКАЦИJЕ СОФТВЕРА

2.3. Решавање линеарних једначина с једном непознатом

Први корак у дефинисању случајне променљиве је. дефинисање и исписивање свих могућих eлементарних догађаја.

Теорија електричних кола

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

СИСТЕМ ЛИНЕАРНИХ ЈЕДНАЧИНА С ДВЕ НЕПОЗНАТЕ

Анализа Петријевих мрежа

ЗАШТИТА ПОДАТАКА Шифровање јавним кључем и хеш функције. Diffie-Hellman размена кључева

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ И НАУКЕ ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

Логистичка регресиjа

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

Објектно оријентисано програмирање

Objektno orijentisano programiranje

Скупови (наставак) Релације. Професор : Рака Јовановић Асиситент : Јелена Јовановић

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ И НАУКЕ ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

Прост случаjан узорак (Simple Random Sampling)

Положај сваке тачке кружне плоче је одређен са поларним координатама r и ϕ.

6.2. Симетрала дужи. Примена

Упутство за избор домаћих задатака

предмет МЕХАНИКА 1 Студијски програми ИНДУСТРИЈСКО ИНЖЕЊЕРСТВО ДРУМСКИ САОБРАЋАЈ II ПРЕДАВАЊЕ УСЛОВИ РАВНОТЕЖЕ СИСТЕМА СУЧЕЉНИХ СИЛА

Увод у теориjу игара и игра инспекциjе

Параметарски и непараметарски тестови

ТРАПЕЗ РЕГИОНАЛНИ ЦЕНТАР ИЗ ПРИРОДНИХ И ТЕХНИЧКИХ НАУКА У ВРАЊУ. Аутор :Петар Спасић, ученик 8. разреда ОШ 8. Октобар, Власотинце

Екстремне статистике поретка и примjене у неживотном осигурању

Количина топлоте и топлотна равнотежа

Семинарски рад из линеарне алгебре

6.1. Осна симетрија у равни. Симетричност двеју фигура у односу на праву. Осна симетрија фигуре

Хомогена диференцијална једначина је она која може да се напише у облику: = t( x)

5.2. Имплицитни облик линеарне функције

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ И НАУКЕ ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

МАТРИЧНА АНАЛИЗА КОНСТРУКЦИЈА

ИНФОРМАЦИJА ПЕРЦЕПЦИJЕ слобода, демократиjа и физика

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

Нестандардна анализа као почетна настава анализе

ЛИНЕАРНА ФУНКЦИЈА. k, k 0), осна и централна симетрија и сл. 2, x 0. У претходном примеру неке функције су линеарне а неке то нису.

2. EЛЕМЕНТАРНЕ ДИОФАНТОВЕ ЈЕДНАЧИНЕ

Објектно орјентисано програмирање. Владимир Филиповић Александар Картељ

4. Троугао. (II део) 4.1. Појам подударности. Основна правила подударности троуглова

ЗАШТИТА ПОДАТАКА. Шифровање јавним кључем и хеш функције. Diffie-Hellman размена кључева

8.2 ЛАБОРАТОРИЈСКА ВЕЖБА 2 Задатак вежбе: Израчунавање фактора појачања мотора напонским управљањем у отвореној повратној спрези

Предмет: Задатак 4: Слика 1.0

АУТОМАТСКО ГЕНЕРИСАЊЕ И ПРОВЕРАВАЊЕ УСЛОВА ИСПРАВНОСТИ ПРОГРАМА

Универзитет у Београду, Саобраћајни факултет Предмет: Паркирање. 1. вежба

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

ГЕОМЕТРИJСКА СВОJСТВА АНАЛИТИЧКИХ ФУНКЦИJА

Факултет организационих наука Центар за пословно одлучивање. PROMETHEE (Preference Ranking Organization Method for Enrichment Evaluation)

АУТОМАТСКО РЕШАВАЊЕ КОНСТРУКТИВНИХ ПРОБЛЕМА У ГЕОМЕТРИJИ

ПРИРОДА ВРЕМЕНА. информациjа материjе термодинамика теориjа релативности квантна механика. принцип вероватноће у физици

1 ПРОСТОР МИНКОВСКОГ

У н и в е р з и т е т у Б е о г р а д у Математички факултет. Семинарски рад. Методологија стручног и научног рада. Тема: НП-тешки проблеми паковања

L кплп (Калем у кплу прпстпперипдичне струје)

УНАПРЕЂИВАЊЕ SMT РЕШАВАЧА КОРИШЋЕЊЕМ CSP ТЕХНИКА И ТЕХНИКА ПАРАЛЕЛИЗАЦИJЕ

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА ТЕСТ МАТЕМАТИКА

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

1. 2. МЕТОД РАЗЛИКОВАЊА СЛУЧАЈЕВА 1

C кплп (Кпндензатпр у кплу прпстпперипдичне струје)

Вектори vs. скалари. Векторске величине се описују интензитетом и правцем. Примери: Померај, брзина, убрзање, сила.

6. ЛИНЕАРНА ДИОФАНТОВА ЈЕДНАЧИНА ах + by = c

Аксиоме припадања. Никола Томовић 152/2011

КРУГ. У свом делу Мерење круга, Архимед је први у историји математике одрeдио приближну вред ност броја π а тиме и дужину кружнице.

Развоj и анализа метахеуристичких метода за испитивање задовољивости формула у вероватносним логикама

Теорија електричних кола

Писмени испит из Теорије површинских носача. 1. За континуалну плочу приказану на слици одредити угиб и моменте савијања у означеним тачкама.

ТЕСТ МАТЕМАТИКА УПУТСТВО ЗА ПРЕГЛЕДАЊЕ

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

АНАЛОГНА ЕЛЕКТРОНИКА ЛАБОРАТОРИЈСКЕ ВЕЖБЕ

ИСПИТИВАЊЕ СВОJСТАВА КОМПЛЕКСНИХ МРЕЖА СА ДИСКРЕТНОМ ДИНАМИКОМ

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ, НАУКЕ И ТЕХНОЛОШКОГ РАЗВОЈА ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

1. Модел кретања (1.1)

ОБЛАСТИ: 1) Тачка 2) Права 3) Криве другог реда

Универзитет у Београду Математички факулет. Фибоначиjев хип и примене

7.3. Површина правилне пирамиде. Површина правилне четворостране пирамиде

Објектно орјентисано програмирање. Владимир Филиповић Александар Картељ

Institute of Informatics and Software Engineering Faculty of Informatics and Information Technologies Slovak University of Technology in Bratislava

ЕНЕРГЕТСКИ ПРЕТВАРАЧИ 2 (13Е013ЕП2) октобар 2016.

ЗБИРКА РЕШЕНИХ ЗАДАТАКА ЗА ПРИЈЕМНИ ИСПИТ ИЗ МАТЕМАТИКЕ

АНАЛИТИЧКА ГЕОМЕТРИJА. Владица Андреjић ( ) УНИВЕРЗИТЕТ У БЕОГРАДУ МАТЕМАТИЧКИ ФАКУЛТЕТ БЕОГРАД 2015.

4. ЗАКОН ВЕЛИКИХ БРОЈЕВА

Cook-Levin: SAT је NP-комплетан. Теодор Најдан Трифунов 305M/12

ЗАВРШНИ РАД КЛИНИЧКА МЕДИЦИНА 5. школска 2016/2017. ШЕСТА ГОДИНА СТУДИЈА

Dynamic types, Lambda calculus machines Section and Practice Problems Apr 21 22, 2016

Република Србија МИНИСТАРСТВО ПРОСВЕТЕ И НАУКЕ ЗАВОД ЗА ВРЕДНОВАЊЕ КВАЛИТЕТА ОБРАЗОВАЊА И ВАСПИТАЊА

РАЧУНАРСТВО И ИНФОРМАТИКА 3. разред

РЕШЕНИ ЗАДАЦИ СА РАНИЈЕ ОДРЖАНИХ КЛАСИФИКАЦИОНИХ ИСПИТА

Теорија друштвеног избора

РЕШЕЊА ЗАДАТАКА - IV РАЗЕД 1. Мањи број: : x,

Динамика. Описује везу између кретања објекта и сила које делују на њега. Закони класичне динамике важе:

Transcript:

Имплементациjа монада у програмском jезику Swift 1.1 Ивица Миловановић Садржаj Монаде су моћан и ефективан алат из арсенала функционалног програмирања. У овом раду ћемо показати како се ове структуре, настале у оквиру математичке теориjе категориjа, а популаризоване кроз програмски jезик Haskell, могу имплементирати и користити у програмском jезику Swift, коjим се израђуjу апликациjе за OS X и jедну од две наjпопуларниjе мобилне платформе, ios. Кључне речи Haskell, монаде, Swift I. Увод Монаде су апстрактне структуре настале у оквиру теориjе категориjа. Значаj монада за програмирање описао jе Мођи у свом раду [1], а у практичну употребу су ушле наjпре кроз програмски jезик Haskell [2], [3], [4]. Будући чист функционални jезик, Haskell користи монаде као jедини начин за имплементациjу споредних ефеката и то jе била њихова првобитна намена. Ипак, монаде су знатно генералниjе структуре и у наjширем смислу моделуjу операциjе коjе jе могуће уланчавати и као такве су потенциjално корисне и у другим jезицима, коjи нису фунционално чисти. Све до недавно, скоро да нису коришћене ван Haskell jезика, што због своjе опскурне природе, што због чињенице да синтакса, типови и семантика већине jезика, И. Миловановић, Рачунарски факултет универзитета Унион, Београд, Србиja (email: imilovanovic12@raf.edu.rs).

нарочито оних наjзаступљениjих, као што су C++, Java, Objective- C, C# итд, нису наjпогодниjе за имплементациjу монадског кода. Последњих година се та ситуациjа мења, те се монаде, у разним облицима, поjављуjу у jезицима коjи се користе на главним платформама, као што су Scala (Java платформа) [5], и F# (.NET платформа) [6]. Последњи у низу модерних jезика, чиjе су многе одлике инспирисане функционалном парадигмом, jе Swift [7], [8], настао под окриљем компаниjе Apple, ради развоjа апликациjа за OS X и ios платформе. Jезик се може користити за обjектно-орjентисани развоj софтвера, користећи Cocoa и Cocoa Touch оквире [9]. Поред тога, статички типови, инференциjа типа, функциjе првог реда, ламбда изрази, могућност дефинисања додатних оператора, генерички типови итд. су неке од одлика коjе оваj jезик чине веома погодним за писање кода у функционалном стилу. С обзиром на то дa тренутно постоjи преко милион апликациjа написаних за ios, а да je Swift jезик будућности за ову платформу, изузетна jе прилика да се функционално програмирање промовише као парадигма коjа у многим ситуациjама може да се искористи за писање краћег, jасниjег, прегледниjег и безбедниjег кода. У овом раду показуjемо како се концепт монаде може искористити за побољшавање свакодневног рада са неколико наjкоришћениjих типова у Swift jезику. A. Дефинициja Поjмови функтора и монаде прецизно и формално су дефинисани у теориjи кaтегориjа [10]. Ако су C и D категориjе, тада функтор F сваком X A придружуjе обjекат F (X) B и сваком морфизму f : X Y A придружуjе морфизам F (f) : F (X) F (Y ) B. Сваки функтор мора да очува морфизме идентитета и композициjе. Ендофунктор jе функтор коjи дефинише пресликавање категориjе у себе саму. Монада jе ендофунктор F : C C, заjедно са две придружене природне операциjе, η : I F, где jе I индентитет фунтор у категориjи C, и µ : F F F. Свака монада мора да задовољава леви и десни идентитет и асоциjативност. B. Имплементациjа у програмском jезику Haskell Haskell имплементира функтор и монаду као класе типова [11], [12]. class Functor f where fmap :: (a -> b) -> f a -> f b

class Monad m where ( > >=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b return :: a -> m a fail :: String -> m a Функциjа fmap у функтор класи дефинише пресликавање датог фунтора у себе самог. Класа монада jе на први поглед другачиjа од дефинициjе монаде из теориjе категориjа. Природна операциjа η jе присутна у облику функциjе return, коjа узима обjекат датог типа и поставља га у контекст монаде. Међутим, операциjа µ ниjе декларисана у класи. Додатно, монада не наслеђуjе класу Functor. Уместо тога, у класи се дефинише >>= оператор, коjи jе еквивалентан секвенци операциjа fmap и µ, а практично jе далеко корисниjи од поjединаче примене сваке од ове две операциjе, jер омогућава уланчавање монадских израза. Специjалну улогу за рад са монадама има do-конструкциjа коjа се заснива на овом оператору. Поjединачне операциjе су присутне, уколико су потребне, у облику функциjа liftm односно join. Разлог због коjег монада тренутно не наслеђуjе класу Functor jе историjске природе и та ситуациjа би требало да се промени у новоj итерациjи компаjлера, наjављеноj за фебруар 2015. године. Оператор >> jе сличан оператору >>=, али игнорише резултат свог левог аргумента и узима у обзир само његов монадски ефекат. Ако монада моделуjе операциjу, чиjи резултат може бити вредност или грешка, >>= извлачи евентуални успешни резултат из свог левог аргумента и прослеђуjе га десном аргументу, коjи jе функциjа. Оператор >> такође проверава да ли његов леви аргумент садржи успешни резултат или грешку, али у случаjу успеха не користи дати резултат, већ враћа своj десни аргумент, коjи jе монада, а не функциjа. МекБраjд и Патерсон су показали да jе монадска апстракциjа често сувишна у случаjевима у коjима не постоjи међузависност између поjединачних корака монадског ланца [13] и за такве случаjе су предложили апстракциjу апликативног функтора, коja jе у jезику Haskell такође имплементирана као класа типова [14]: class ( Functor f) => Applicative f where pure :: a -> f a ( <* >) :: f (a -> b) -> f a -> f b Функциjа pure jе идентична монадскоj функциjи return. Оператор <*> омогућава да се функциjа, коjа узима нормалне аргументе и

враћа нормални резултат постави у контекст апликативног функтора и примени на аргументе, коjи су унутар истог тог контекста: pure (f) <*> a1 <*> a2 <*> a3... Израз pure(f) <*> a може се написати као f fmap a. У модулу Applicative дефинисан jе помоћни оператор <$>, коjи jе синоним за fmap. Имаjући ово у виду, претходни кôд се може написати мало другачиjе, у свом идиоматском облику: f <$> a1 <*> a2 <*> a3... Ова техника се назива апликативни стил, jер jе аналогна обичноj примени (апликациjи) функциjа. Свака монада jе апликативни функтор, иако класа Monad тренутно не наслеђуjе класу Applicative, из споменутих историjских разлога. Оператор <*> се може имплементирати коришћењем оператора >>=. Обрнуто не важи. Могуће jе написати инстанце апликативног функтора коjе не могу бити инстанце монаде. Ми се у овом раду нећемо бавити таквим апликативним функторима, већ ћемо за сваку имплементирану монаду написати оператор <*>, како би дати тип могао да се користи у оквиру апликативног стила, када jе то погодниjе. C. Имплементациjа у програмском jезику F# Jезик F# нема могућност дефинисања класа типова jер полиморфизам вишег рода, коjи jе за то неопходан, у овом тренутку не би био компатибилан са остатком.net платформе. Уместо тога, F# користи израчунљиве изразе (Computation Expressions) [15]. Да би се неки тип могао користити као монада, неопходно jе дефинисати класу коjа ће за таj тип имплементирати Bind и Return функциjе, коjе су аналогне Haskell return и >>= функциjама. Након тога jе монаду могуће користити унутар израчунљивог израза, користећи let! команду за везивање монадског резултата за променљиву, односно return команду за позивање Return функциjе, што je аналогно Haskell do нотациjи. Коришћење израчунљивих израза за имплементациjу апликативног функтора ниjе подржано у званичноj верзиjи компаjлера, али jе могуће кроз истраживачку екстензиjу описану у [15]. II. Монаде у jезику Swift A. Детаљи имплементациjе Сваку од монада M<T> имплементирамо на следећи начин:

1) Дефинишемо метод map<u>(f:t->u)->m<u> уколико таj метод ниjе већ присутан у стандардноj библиотеци за дату монаду; 2) Дефинишемо глобалну функциjу flatten<t>(m:m<m<t>>)->m<t>. Функциjа flatten еквивалентна jе природноj операциjи µ; 3) Дефинишемо глобалну функциjу pure<t>(value:t)->m<t>, коjа jе еквивалентна природноj операциjи η и Haskell функциjи return. 4) Дефинишемо метод bind<u>(f:t->m<u>)->m<u>, коjи jе аналоган Haskell >>= оператору и F# Bind функциjи и метод bind<u>(m:m<u>)->m<u>, аналоган Haskell >> оператору. Функциjа pure (3) ниjе увек неопходна у пракси, jер се уместо ње могу користити конструктори или синтаксичке пречице уколико постоjе за дати тип, али jе ипак наводимо ради комплетности. Уколико ниjе другачиjе назначено, bind методе (4) имплементирамо користећи претходно дефинисане map и flatten операциjе: extension M { func bind <U >(f: T -> M<U >) -> M<U> { return flatten ( self. map (f)) func bind <U >( monad : M<U >) -> M<U> { return self. bind { _ in monad Ова имплементациjа jе елегантна jер следи из природних монадских операциjа, али ниjе увек наjефикасниjа у Swift jезику. Због тога смо за монаду Array<T> написали ефикасниjу императивну имплементациjу. Коначно, ради коришћења датих монада у оквиру апликативног стила, имплементирали смо оператор <^>, коjи jе заправо глобална map функциjа, аналогна Haskell оператору <$>, и оператор <*> аналоган истоименом Haskell оператору: infix operator <^> { associativity left infix operator <* > { associativity left func <^> <T, U >(f: T -> U, monad : M<T >) -> M<U> { return monad. map (f)

func <*> <T, U >( mf: M<T -> U>, monad : M<T >) -> M<U> { return mf. bind { f in monad. bind { value in f( value ) За оператор <*> jе, као и за метод bind, ова природна имплементациjа често недовољно ефикасна, те смо и за оваj оператор написали ефикасниjу императивну имплементациjу за Array<T> монаду, док остале монаде подразумевано користе претходну дефиницуjу. Функциjе више променљивих писали смо у облику коjи дозвољава парциjалну апликациjу, тамо где jе то неопходно (f(a: A)(b: B) уместо f(a: A, b: B)). У своjоj првоj итерациjи Swift не поседуjе могућност имплементациjе полиморфних монада као Haskell, нити поседуjе конструкциjе налик израчунљивим изразима у F#. Уколико дизаjнери jезика одлуче да jедно од та два или нешто треће укључе у будуће верзиjе, биће тривиjално да се имплементациjе, представљене у овом раду, уклопе у нову синтаксу. B. Глобалне функциjе, оператори и методи Важно техничко питање коjе се поставља приликом имплементациjе монада jе избор између глобалних функциjа, оператора и метода. Глобалне функциjе нису добар избор за операциjе коjе су предвиђење за уланчавање jер захтеваjу угњеждене позиве (нпр. bind(bind(monad, f1), f2)). Помоћу оператора оваj проблем се елегантно решава тако што се приликом позивања пишу између своjих аргумената (нпр. monad >>= f1 >>= f2). Мана оператора jе то што сами по себи нису довољно разумљиви и њихово значење се знатно разликуjе од jезика до jезика. Haskell програмер би одмах препознао >>= као оператор за монадско везивање, али истоимени оператор jе у Swift стандардноj библиотеци дефинисан као оператор за манипулисање битовима. Помоћу метода могу се решити оба проблема. Могу им се доделити разумљива имена, као глобалним функциjама, а позиваjу се веома слично као оператори (нпр. monad.bind(f1).bind(f2)). Swift омогућава дефинисање метода на свим типовима (класама, структурама, енумерациjма и униjама дискриминатора), a коришћењем екстензиjа методе jе могуће додати чак и типовима за коjе ниjе доступан изворни кôд. Коначно, потенциjално важна практична

предност метода jе то што су бољи за аутоматско комплетирање кода у развоjним окружењима. Ово jе важно не само за брже писање кода, већ и за спонтано откривање метода од стране програмера. Метод bind поjавиће се у листи доступних метода сваки пут када програмер ради са датом монадом, што ниjе случаj са операторима. О доступности оператора може се сазнати jедино кроз исчитавање документациjе или кроз интеракциjу са другим програмерима. Идеално бисмо желели да све операциjе у овом раду имплементирамо као методе, али то ниjе могуће због тренутних техничких ограничења jезика. Функциjа flatten мора бити глобална jер тренутно ниjе могуће специjализовати методе генеричких типова. Из истог разлога смо користили оператор <*> уместо одговараjућег метода. Креатор Swift jезика, Крис Латнер, наговестио jе на званичном развоjном форуму компаниjе Apple да би се ово могло променити у будућим верзиjама компаjлера [16] и његова изjава подупире нашу одлуку да изаберемо методе када год jе то могуће. C. Optional<T> Тип Optional<T>, аналоган Haskell Maybe a типу, моделуjе могуће одсуство дате вредности. Део jе стандардне Swift библиотеке у коjоj jе дефинисан као униjа дискриминатора, на следећи начин: enum Optional <T > { Some (T) None Ово jе jедан од наjважниjих типова у свакодневном програмирању, нарочито приликом коришћења Cocoa и Cocoa Touch оквира. Наиме, Swift нема null односно nil референце. Свака референца мора показивати на конкретни постоjећи обjекат у мемориjи. Али, с обзиром на то да су Cocoa и Cocoa Touch писани у Objective-C jезику, nil jе веома често аргумент метода или враћена вредност. Све те nil вредности су премошћене у Optional<T>. Компаjлер аутоматски пакуjе вредности коjе нису nil у.some(t), a вредности коjе су nil у.none. Иако Swift нема nil референце, кључна реч nil постоjи у jезику и означава литерал коjим се може представити било коjи тип коjи имплементира NilLiteralConvertible протокол, а Optional<T> jе jедан од њих. У пракси jе наjчешће nil синоним за Optional.None. Уграђене синтаксичкe пречицe за рад са Optional<T> наведене су у Tабели 1.

Табела 1: Синтаксичке пречице за рад са Optional<T> типом основна синтакса пречица значење let о: Optional<T> let о: T? декларациjа let о: T? =.Some(5) let о: T? = 5 додела let о: T? =.None let о: T? = nil додела switch o {case.some(let v): if let v = o { отпакивање if let v = o {v.method() v?.method() уланчавање Optional<T> чини рад са референцама далеко безбедниjим и отклања читаву класу могућих грешака у коду. Поред тога, тип jе генералниjи од null референци, jер може изразити и одсуство типова коjи нису референце, већ вредности. Ипак, и поред споменутих синтаксичких пречица, понекад рад за овим типом може довести до незграпног кода са угњежденим if блоковима, коjи jе тежак за читање и одржавање. Монадска апстракциjа може бити добра алтернатива у таквим случаjевима. Метод map jе већ дефинисан у стандардноj библиотеци за оваj тип. Операциjа мапирања враћа.none ако jе Optional<T> jеднак.none. У супротном, примењуjе дату функциjу f : T U на садржаj Optional<T> и враћа резултат као Optional<U>. Функциjа pure jе тривиjална - узима дату вредност и враћа jе запаковану у Optional<T>. Функциjа flatten враћа унутрашњи Optional<T> или.none, уколико jе спољашњи Optional<T> jеднак.none: func pure <T >( value : T) -> T? { return value func flatten <T >( optional : T??) -> T? { if let inneroptional = optional { return inneroptional else { return nil Монадски bind методи, апликативни оператор <*> и oператор <^> користе претходно описану подразумевану имплементациjу. Уграђени?. оператор за уланчавање (Табела 1) jе заправо синтаксичка пречица за bind метод: let maybec1 = a?.b ()?. c()

let maybec2 = a. bind { $0.b(). bind { $0.c() Предност bind jе што се може користити са произвољним функциjама и методима, укључуjући и ламбда изразе за jеднократну употребу. Примена овог метода у интерактивном Swift окружењу приказана jе на Сл. 1.a. (a) (b) Сл. 1. (a) Примена монадског bind метода за уланчавање операциjа коjе могу вратити nil уколико бинарна операциjа не постоjи за дати симбол; (b) Примена апликативног <*> оператора за рад са независним операциjама, од коjих свака може вратити nil Без bind метода, решавање сличног проблема, у тренутноj верзиjи jезика, захтева коришћење угњеждених if-let блокова. Додавање сваке следеће функциjе у ланац if-let везивања, захтева додатно угњеждење, што врло брзо постаjе потпуно нечитљиво, док приликом коришћења bind метода читљивост остаjе иста за било коjи броj додатих функциjа. Апликативни стил jе погодниjи када опциони резултати не зависе jедан од другог, већ су независни аргументи неке функциjе (Сл. 1.b). Слично bind методу, предност апликативног стила нарочито долази до изражаjа када функциjа, коjа се примењуjе на опционе вредности, има много аргумената.

D. Result<T> Због аутоматског броjања референци, ухватљиви изузеци нису погодни за рад са операциjама коjе могу резултирати грешком у Swift и Objective-C jезицима. Уместо тога, Cocoa и Cocoa Touch оквири дефинишу NSError класу коjа енкапсулира информациjе о грешци [17]. Пошто методи у Objective-C, jезику у коjем су написани Cocoa и Cocoa Touch, немаjу могућност да врате више од jедне вредности, NSError се користи тако што се прослеђуjе по референци: var maybeerror : NSError? let failableresult = readfile (& maybeerror ) if let result = failableresult { // use result else if let error = maybeerror { // deal with error Проблем претходног кода jе што jе поприлично неелегантан у Swift jезику, нарочито ако jе неопходно проћи кроз ланац операциjа од коjих свака може да резултуjе грешком. Jедно могуће решење jе да се као резултат операциjе врати пар, коjи садржи резултат или грешку. func readfile () -> ( Result?, NSError?) Проблем овог приступа jе што пар и генерално n-торка не представља добро резултат коjи може бити или успех или грешка, али не и оба. Поред тога, резултат и грешка мораjу нужно да буду упаковани у Optional<T>. Решења оба проблема jе алгебарски тип Result<T>: class Box <T > { let value : T init (_ value : T) { self. value = value enum Result <T > { case Success (Box <T >) case Error ( NSError ) init (_ value : T) { self =. Success ( Box ( value ))

Класа Box<T> jе неопходна jер Swift компаjлер у верзиjи 1.1 не дозвољава енумерациjе коjе, поред генеричке придружене вредности (у овом случаjу T), садрже и негенеричке (у овом случаjу NSError). Када се Result<T> користи у монадском или апликативном стилу, ово не представља велики проблем, jер тада одговараjући оператори и методи обављаjу отпакивање и запакивање иза сцене. Операциjу map над типом Result<T> дефинисали смо на следећи начин: func map <U >( f: T -> U) -> Result <U > { switch self { case. Success ( let boxedvalue ): return. Success ( Box (f( boxedvalue. value ))) case. Error ( let error ): return. Error ( error ) Уколико jе Result<T> jеднако Success, тада map узима придружени резултат, примењуjе прослеђену функциjу на таj резултат и враћа нови резултат, запакован у Result<T>. Монадска операциjа pure jе тривиjална - узима прослеђену вредност a и враћа.success(a). Функциjа flatten враћа унутрашњи Result<T> или.error(e), уколико jе спољашњи Result<T> jеднак.error(e): func pure <T >( value : T) -> Result <T > { return. Success ( Box ( value )) func flatten <T >(r: Result < Result <T > >) -> Result <T> { switch r { case. Success ( let boxedresult ): return boxedresult. value case. Error ( let error ): return. Error ( error ) Као и у случаjу Optional<T>, монадски bind методи, апликативни оператор <*> и оператор <^> користе подразумевану имплементациjу. Нови методи и функциjе се могу од самог почетка дизаjнирати тако да враћаjу Result<T>, а за већ постоjеће се могу написати помоћне функциjе на следећи начин: func readfile () -> Result < String > { var maybeerror : NSError?

let failableresult = readfile (& maybeerror ) if let result = failableresult { return Result ( result ) else if let error = maybeerror { return. Error ( error ) Функциja perform, коjу смо користили да илуструjемо третирање Optional<T> као монаде (Сл. 1.a), може се имплементирати тако да, уместо опционог резултата, враћа Result<T> (Сл. 2.а). (a) (b) Сл. 2. (a) Примена монадских bind метода за уланчавање операциjа коjе могу вратити Result.Error уколико бинарна операциjа не постоjи за дати симбол; (b) Примена апликативног <*> оператора за рад са независним операциjама, од коjих свака може вратити Result.Error Kôд приказан на Сл. 2. jе практично идентичан еквивалентном коду за тип Optional<T>. Овде се види природност монадске апстракциjе у функционалним jезицима, чак и ако ти jезици не поседуjу специjалну синтаксу за монаде. Исто важи и за апликативни стил. Функциjа max, дефинисана у коду приказаном на Сл. 1.b, може се користити са Result<T> на потпуно исти начин као са Optional<T> (Сл. 2.b). E. Array<T> Третирањем низова као монада могу се имплементирати операциjе чиjи jе резултат недерминистички, тj. оне операциjе код коjих се, уместо jедног тачно одређеног резултата, добиjа више могућих.

Операциjа map jе већ дефинисана за Array<T> у стандардноj библиотеци као метод, те оператор <^> jедноставно позива таj метод. Монадска операциjа pure узима дати елемент и враћа га упакованог у низ, док операциjа flatten низ низова трансформише у jедан низ, користећи метод reduce: pure <T >( element : T) -> [T] { return [ element ] func flatten <T >( array : [[T]]) -> [T] { return array. reduce ([]) { $0 + $1 Имплементациjе монадских метода и апликативног оператора би могле jедноставно да се изведу из претходних функциjа, али та имплементациjа не би била довољно ефикасна jер би више пута пролазила кроз исти низ. Због тога смо за bind и <*> написали ефикасниjе императивне имплементациjе: extension Array { func bind <U >(f: T -> [U]) -> [U] { var result = [U ]() for element in self { result += f( element ) return result func bind <U >( array : [U]) -> [U] { return self. count > 0? array : [] public func <*><T, U >( fs: [T -> U], array : [T]) -> [U] { var results = [U ]() for f in fs { for element in array { results += [ f( element )] return results

На Сл. 3. приказана jе примена монадских метода и апликативног оператора на низове, у интерактивном Swift окружењу. (a) (b) Сл. 3. (а) Примена монадског bind метода за растављање низа ниски у низ карактера; (b) Примена апликативног <*> оператора за конструкциjу свежња карата из низа знакова и вредности III. Закључак Резултати овог рада показуjу погодност Swift jезика за jедноставну имплементациjу и коришћење монада. С обзиром на то да jе Swift потпуно нови jезик чиjе спецификациjе jош увек нису потпуно одређене, остаjе отворено питање у коjоj мери и како ове и сличне технике из традиционалних функционалних jезика треба примењивати у продукциjском коду. Jедно занимљиво питање, о коjем се мора размишљати приликом имплементациjе функционалних техника, jе избор између метода и глобалних функциjа. Методи су, као што смо рекли, вероватно пожељне у већини случаjева, али су у трентуноj верзиjи jезика глобалне функциjе нешто моћниjе jер су jедини начин за имплементациjу одређених генеричких апстракциjа. Дефнитивни одговори на ова питања ће морати да сачекаjу Swift 2.0, можда и 3.0 верзиjу. Одговори ће, између осталог, зависити и од евентуалних помоћних синтаксичких конструкциjа коjе ће jезик садржати. У међувремену су, како монаде, тако и друге функционалне апстракциjе, несумњиво одличан начин да се упрости приватна имплементациjа. Међутим, те апстракциjе ипак треба опрезно и постепено откривати као jавни интерфеjс. Jавни функционални API може да буде проблематичан, не само са техничке стране, већ и због тога што су традиционални

развоjни тимови углавном састављени од програмера образованих у оквиру обjектно-орjентисане парадигме. Да би функционалне технике доживеле своj пуни потенциjал за повећање продуктивности, наjпре jе неопходна едукациjа и прилагођавање тимова. Овим се, такође, поjављуjе занимљив практични и истраживачки проблем за садашње софтверске фирме у коjима функционално програмирање ниjе више само академска творевина, већ ефикасно средство наjвећих комерциjалних развоjних плаформи. Литература [1] E. Moggi, Notions of computation and monads, Information and Computation, vol. 93, no. 1, pp. 55 92, 1991, selections from 1989 {IEEE Symposium on Logic in Computer Science. [Online]. Available: http://www.sciencedirect.com/science/article/ pii/0890540191900524 [2] S. L. Peyton Jones and P. Wadler, Imperative functional programming, in Proceedings of the 20th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, ser. POPL 93. New York, NY, USA: ACM, 1993, pp. 71 84. [Online]. Available: http://doi.acm.org/10.1145/158511.158524 [3] J. Launchbury and S. L. Peyton Jones, State in haskell, Lisp Symb. Comput., vol. 8, no. 4, pp. 293 341, Dec. 1995. [Online]. Available: http://dx.doi.org/10.1007/bf01018827 [4] P. Wadler, Monads for functional programming, in Advanced Functional Programming, ser. Lecture Notes in Computer Science, J. Jeuring and E. Meijer, Eds. Springer Berlin Heidelberg, 1995, vol. 925, pp. 24 52. [Online]. Available: http://dx.doi.org/10.1007/ 3-540-59451-5_2 [5] Scala language, http://www.scala-lang.org. [6] F# language, http://fsharp.org. [7] Swift language, http://www.apple.com/swift/. [8] The Swift programming language. [Online]. Available: https://developer.apple.com/library/mac/documentation/swift/ Conceptual/Swift_Programming_Language/index.html

[9] Using Swift with Cocoa and Objective-C. [Online]. Available: https://developer.apple.com/library/prerelease/ios/ documentation/swift/conceptual/buildingcocoaapps/ [10] S. Lane, Categories for the Working Mathematician, ser. Graduate Texts in Mathematics. Springer New York, 1998. [Online]. Available: http://books.google.rs/books?id=ebvhyc4z8hqc [11] Haskell Functor, https://www.haskell.org/haskellwiki/functor. [12] Haskell Monad, https://www.haskell.org/haskellwiki/monad. [13] C. Mcbride and R. Paterson, Applicative programming with effects, J. Funct. Program., vol. 18, no. 1, pp. 1 13, Jan. 2008. [Online]. Available: http://dx.doi.org/10.1017/s0956796807006326 [14] Haskell Applicative Functor, http://hackage.haskell.org/package/ base-4.7.0.2/docs/control-applicative.html. [15] T. Petricek and D. Syme, The F# computation expression zoo, in Practical Aspects of Declarative Languages, ser. Lecture Notes in Computer Science, M. Flatt and H.-F. Guo, Eds. Springer International Publishing, 2014, vol. 8324, pp. 33 48. [Online]. Available: http://dx.doi.org/10.1007/978-3-319-04132-2_3 [16] Chris Lattner on choosing between methods and global functions in Swift, https://devforums.apple.com/message/1074064#1074064. [17] Introduction to error handling programming guide for Cocoa, 2011. [Online]. Available: https://developer.apple.com/library/ mac/documentation/cocoa/conceptual/errorhandlingcocoa/ ErrorHandling/ErrorHandling.html Abstract Monads are powerful constructs used in functional programming for managing processes with side effects, but also for modelling and building complicated computations. Monads are theoretically founded in Category Theory and widely popularised by the Haskell programming language. In this paper, we show how monads can be implemented and used in Swift, the new language for developing ios and OS X applications.

MONADS IN SWIFT Ivica Milovanović