Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
pl:miw:2009:miw09_mercury [2009/08/23 19:23]
jsi08
— (aktualna)
Linia 1: Linia 1:
-====== Opis ====== 
-Michał Kołodziej, <​kolodziej.michal@gmail.com>​ 
- 
-Read on the  
-[[http://​www.cs.mu.oz.au/​research/​mercury/​|Mercury language]]. 
-Describe concepts, examples, ​ 
-compare to Prolog and [[http://​haskell.org/​|Haskell]]. 
- 
-[[http://​home.agh.edu.pl/​~mszpyrka/​dydujk:​ppdata:​pp|haskell]] 
- 
-====== Spotkania ====== 
-===== 20090416 ==== 
-  * ... 
- 
-===== 20090326 ==== 
- 
-====== Projekt ====== 
-===== Introduction ===== 
-==== What is Mercury? ==== 
-From: "//​Mercury Language Reference//",​ introduction:​ 
- 
-Mercury is a new general-purpose programming language, designed and implemented by a small group of researchers at the University of Melbourne, Australia. Mercury is based on the paradigm of purely declarative programming,​ and was designed to be useful for the development of large and robust “real-world” applications. It improves on existing logic programming languages by providing increased productivity,​ reliability and efficiency, and by avoiding the need for non-logical program constructs. Mercury provides the traditional logic programming syntax, but also allows the syntactic convenience of user-defined functions, smoothly integrating logic and functional programming into a single paradigm. 
- 
-Mercury requires programmers to supply type, mode and determinism declarations for the predicates and functions they write. The compiler checks these declarations,​ and rejects the program if it cannot prove that every predicate or function satisfies its declarations. This improves reliability,​ since many kinds of errors simply cannot happen in successfully compiled Mercury programs. It also improves productivity,​ since the compiler pinpoints many errors that would otherwise require manual debugging to locate. The fact that declarations are checked by the compiler makes them much more useful than comments to anyone who has to maintain the program. The compiler also exploits the guaranteed correctness of the declarations for significantly improving the efficiency of the code it generates. 
- 
-To facilitate programming-in-the-large,​ to allow separate compilation,​ and to support encapsulation,​ Mercury has a simple module system. Mercury'​s standard library has a variety of pre-defined modules for common programming tasks — see the Mercury Library Reference Manual. 
- 
-==== Why Mercury? ==== 
-**Mercury** is developed to solve to main problems that appears in another logic programming languages (e.g. Prolog): 
-  * poor error detection at compile time, and 
-  * low performance 
- 
- 
-==== Mercury language features ==== 
- 
-  * purely declarative:​ predicates and functions in Mercury do not have non-logical side effects 
-  * strongly typed 
-  * strongly moded 
-  * strong determinism system 
-  * module system 
-  * supports higher-order programming,​ with closures, currying, and lambda expressions 
- 
-==== Mercury OS platforms ==== 
-Mercury should work on following platforms: 
-    * x86 machines running Debian Linux 
-    * x86 machines running Microsoft Windows XP 
-    * x86 machines running Solaris 9 (SunOS 5.9) 
-    * x86_64 machines running Debian Linux 
-    * Apple PowerPC machines running Mac OS 10.3 and above  
- 
-==== Mercury interoperability ==== 
-The Mercury implementation compiles to a wide variety of target languages on a wide variety of platforms. Target language back-ends include: 
- 
-Mature: 
-  * Low level C 
-  * High level C 
-Alpha- or beta-release quality: 
-  * Microsoft'​s .NET 
-  * Native code 
-  * Java 
- 
-====== Sprawozdanie ====== 
-To sprawozdanie zostało napisane w maju 2009 r. 
- 
- 
-===== Jak zacząć? ===== 
-Informacje dotyczące instalacji kompilatora,​ kompilowania i uruchamiania programów napisanych w Mercurym pod Windows XP 
-==== Do pobrania ==== 
-Aby zacząć pracę z Mercurym i Haskellem należy pobrać następujące pliki: 
- * Kompilator Mercury ze strony [[http://​www.cs.mu.oz.au/​research/​mercury/​download/​release.html]],​ ja użyłem ostatniej stabilnej wersji kompilatora [[http://​www.mercury.cs.mu.oz.au/​download/​files/​mercury-compiler-0.13.1.tar.gz|Mercury 0.13.1 compiler]] w postaci źródłowej 
- * [[http://​www.cygwin.com/​|Cygwin]],​ używalem Cygwin.dll w versji 1.5.25-15 
- * Pakiety dla cygwina (można ściągnąć za pomocą automatycznego instalatora cygwina): 
- * gcc v. 3.4.4-3 ​ 
- * make v. 3.81-2 
- * bison v. 2.3-1 
- * gcc-tools-automake 
- * gcc-tools-autoconf 
- * readline v. 5.2.12-10 i 5.2.13-11 
- * Kompilator i narzędzia dla Haskella - Haskell Platform, dostępney na stronie [[http://​www.haskell.org]],​ użyłem [[http://​hackage.haskell.org/​platform/​2009.2.0/​HaskellPlatform-2009.2.0-r1-setup.exe|wersji Beta 2009.2.0]] 
- * Edytor tekstu obsługujący *NIXowy format plików, np. [[http://​notepad-plus.sourceforge.net/​uk/​site.htm|Notepad++]] 
- * Program do rozpakowywania plików, które poprawnie traktuje pliki *NIXowe, np. [[http://​www.izarc.org/​|IZARC]] lub [[http://​www.7-zip.org/​|7zip]] 
- 
-==== Instalacja Cygwin ==== 
-Należy uruchomić instalator Cygwina (setup.exe). Postępować zgodnie ze wskazówkami i zainstalować pakiety opisane w [[miw09_mercury#​Do pobrania|poprzedniej sekcji]]. W dalszej części zakładał będę, że Cygwin został zainstalowany w katalogu "​C:/​cygwin",​ natomiast katalog domowy użytkownika jest "​C:​\cygwin\home\USER_NAME"​. 
- 
- 
-==== Instalacja Haskell ==== 
-Uruchomić instalator Haskell Platform, postępować zgodnie z instrukcjami. Zakładam że Haskell został zainstalowany do folderu "​C:​\Program Files\Haskell Platform"​ 
- 
-==== Instalacja Mercury ==== 
-Szczegółowe informacje o instalacji z kodu źródłowego można znaleźć w archiwum kompilatora,​ w pliku README. Poniżej przedstawione zostały kroki potrzebne do typowej instalacji kompilatora:​ 
- * rozpakować archiwum tar.gz np. do katalogu "​~/​USER_NAME/​tymczasowy",​ 
- * uruchomić powłokę cygwina, 
- * wywołać komendę <code bash>cd tymczasowy</​code>​ 
- * wywołać komendę <code bash>cd mercury-compiler-0.13.1</​code>​ 
- * wywołać komendę <code bash>sh configure && make && make install</​code>​ ja użylem <code bash>sh configure --disable-most-grades && make && make install</​code>​ w celu przyśpieszenia instalacji. (Krok ten może potrwać na prawdę długo!), 
- * jeśli instalacja odbędzie się pomyślnie, kompilator Mercury zostanie zainstalowany do katalogu "​C:/​cygwin/​usr/​local/​mercury-0.13.1"​ 
- 
- 
-Żeby móc używać kompilatora mercury: 
- * __z poziomu linii komend systemu Windows XP__ należy dodać do ścieżki systemu Windows XP (Panel sterowania -> System -> zakładka Zaawansowane -> przycisk Zmienne środowiskowe -> grupa zmienne systemowe, zaznaczyć //Path//, przycisk Edycja) katalogi "​C:/​cygwin/​usr/​local/​mercury-0.13.1/​bin"​ oraz "​C:/​cygwin/​bin"​ (kompilator Mercurego potrzebuje dostępu do kompilatora gcc) 
- * __z powłoki cygwina__, należy dodać do pliku .bashrc, znajdującego się w katalogu home lub użytkownika ("​C:/​cygwin/​home"​ lub "​C:/​cygwin/​home/​USER_NAME",​ jeżeli nie ma takiego pliku, należy go utworzyć) linię kodu: <code bash>​PATH=/​usr/​local/​mercury-0.13.1/​bin:​$PATH</​code>​ 
- 
-==== Kompilowanie i uruchamianie programów w Mercurym ==== 
-Aby skompilować program w pliku //​nazwa_pliku_źródłowego.m//​ należy: 
- * albo w linii komend Windows XP kompilator wywołuje się komendą <code winbatch>​mercury --make nazwa_pliku_źródłowego</​code>​ 
- * albo w powłoce Cygwin'​a kompilator wywołuje się komendą <code winbatch>​mmc --make nazwa_pliku_źródłowego</​code>​ 
-Zostanie utworzony plik wykonywalny //​nazwa_pliku_źródłowego.exe//​. Do jego uruchomienia potrzebna jest biblioteka //​cygwin1.dll//,​ którą należy skopiować z katalogu bin Cygwina ("​C:/​cygwin/​bin/​cygwin1.dll"​),​ do katalogu w którym znajduje się plik wykonywalny. 
- 
-==== Hello world! ==== 
-Poniżej jest pokazany program w Mercurym, który umożliwia interakcyjną pracę ze światem zewnętrznym. Tak się składa, że ten prosty program wykorzystuje pewne bardziej zaawansowane koncepcje języka mercury, których nie będę tutaj szczegółowo omawiał. 
-<​code>​ 
-% hello.m 
-:- module hello. 
-:- interface. 
-:- import_module io. 
-:- pred main(io::​di,​ io::uo) is det. 
-:- implementation. 
-:- import_module char, list, string. 
-main(!IO) :- 
-        io.write_string("​Hello,​ World!\n",​ !IO), 
- io.read_char(R,​ !IO). 
-</​code>​ 
-Aby skompilować ten program należy w powłoce cygwina wykonać: 
-<code bash>$ mmc --make hello</​code>​ 
- 
-===== Porównanie Haskell'​a z Mercury'​m ===== 
-Na podstawie "//​Gentle Introduction to Haskell 98//". 
- 
-==== Typy i wartości ==== 
-W Mercurym wszystkie zmienne muszą zaczynać się z dużej litery (w przeciwieństwie do Haskell'​a,​ gdzie wszystkie typy muszą zaczynać się z dużej litery). Nazwy modułów, typów, predykatów,​ funkcji itp. zaczynają się z małej litery. 
- 
-Funkcje, predykaty, tuple, typy są wyrażeniami tak jak typy podstawowe. Mogą one być przekazywane do innych funkcji, predykatów,​ podobnie jak w Haskellu. Typy, funkcje i predykaty mogą być polimorficzne,​ również podobnie jak w Haskellu. 
- 
-  * Podstawowe typy: 
-    * 5:integer 
-    * '​a':​char 
-    * "​abc":​string 
-    * 3.1415:​float 
-  * Predykaty: 
-    * pred, pred(T), pred(T1, T2) 
-  * Funkcje: 
-    * func(T1, T2) = T 
-    * func int = int 
-  * Listy: 
-    * list(int) 
-  * Tuple: 
-    * {}, {T}, {T1, T2}, .... 
-  * Typy dynamiczne: 
-    * univ 
-  * Typy stanu świata (niedeterministyczne):​ 
-    * io.state 
- 
-=== Typy użytkownika === 
-Nowy typ deklaruje się za pomocą słów kluczowych ":- type". Możliwe jest definiowanie typów enumerycznych jak i rekordów. Definicja typu następuje po słowie kluczowym "​--->"​. 
-<​code>​ 
-:- type tree 
-             ​---> ​   empty 
-             ; ​      ​leaf(int) 
-             ; ​      ​branch(tree,​ tree). 
-:- type poliTree(T) 
-             ​---> ​   empty 
-             ; ​      ​leaf(T) 
-             ; ​      ​branch(poliTree(T),​ poliTree(T)). 
-:- type employee 
-             ​---> ​   employee( 
-                            name        :: string, 
-                            age         :: int, 
-                            department ​ :: string 
-                     ). 
-:- type list(T) 
-             ​---> ​   [] 
-             ; ​      [T | list(T)]. 
- 
-</​code>​ 
- 
-W Hasekllu typy użytkownika deklaruje się za pomocą słowa kluczowego "​data"​ i listy konstruktorów oddzielonych "​|"​. Podobnie jak w Mercurym. 
-<code Haskell> 
-data Tree        = Empty | Leaf Int | Branch Tree Tree 
-data PoliTree a  = Empty | Leaf a | Branch (PoliTree a) (PoliTree a) 
-data Employee ​   = Employee {name :: String, age :: Int, department :: String} 
-data List a      = Nil | Cons a (List a) 
-</​code>​ 
- 
-W Mercurym istnieją dodatki syntaktyczne umożliwiające manipulacje polami rekordów (Haskell również wspiera tą funkcjonalność,​ jednak nie można tworzyć własnych funkcji :-( ): 
- 
-<​code>​ 
-% Field selection for maps. 
-% Map ^ elem(Key) = map.search(Map,​ Key). 
-% 
-:- func map.elem(K, map(K, V)) = V is semidet. 
- 
-% Field update for maps. 
-% (Map ^ elem(Key) := Value) = map.set(Map,​ Key, Value). 
-% 
-:- func 'elem :='(K, map(K, V), V) = map(K, V). 
- 
-%uzycie: 
-% inicjalizowanie mapy 
-X = map.insert(map.insert(map.init,​ "​Mercury",​ 1), "​Haskell",​ 2), 
-% zmiana pola 
-Y = X^elem("​Mercury"​) := 2, 
-% odczytanie pola 
-WhoWins = Y ^ elem("​Haskell"​) 
- 
-</​code>​ 
- 
-=== Typy równoważne === 
-Mercury podobnie jak Haskell wspiera definiowanie typów równoważnych. Typy równoważne są definiowane po słowie kluczowym "​==":​ 
-<​code>​ 
-:- type newInt == int. 
-</​code>​ 
-Składnia Haskella: 
-<code Haskell> 
-type NewInt = Int 
-</​code>​ 
- 
-=== Listy === 
-W Mercurym konstruktorem listy jest "​|",​ nie jak w Haskellu ":"​. Dodatkowo listy nie należą do podstawowej biblioteki Mercurego (trzeba je importować ":- import_module list") 
- 
-**Czy są w Mercurym List Comprehensions and Arithmetic Sequences? e.g. ** 
- 
-Haskell oferuje pewne dodatki syntaktyczne dla list:  
-<code Haskell> 
-quicksort ​ []           ​= ​ [] 
-quicksort (x:​xs) ​       =  quicksort [y | y <- xs, y<x ] 
-                        ++ [x] 
-                        ++ quicksort [y | y <- xs, y>=x] 
- 
-qsort2 :: Ord a => [a] -> [a] 
-qsort2 []     = [] 
-qsort2 (x:xs) = qsort2 lesser ++ equal ++ qsort2 greater 
-    where 
-        (lesser,​equal,​greater) = part x xs ([],[x],[]) 
- 
-part :: Ord a => a -> [a] -> ([a],​[a],​[a]) -> ([a],​[a],​[a]) 
-part _ [] (l,e,g) = (l,e,g) 
-part p (x:xs) (l,e,g) 
-    | x > p     = part p xs (l,e,x:g) 
-    | x < p     = part p xs (x:l,e,g) 
-    | otherwise = part p xs (l,x:e,g) 
-</​code>​ 
- 
-niestety brakuje ich w Mercurym (kod ze strony [[http://​en.literateprograms.org/​Quicksort_(Mercury)]]):​ 
-<​code>​ 
-:- module quicksort. 
-:- interface. 
-:- import_module list, int. 
-:- func qsort(list(int)) = list(int). 
-:- mode qsort(in) = out is det. 
-:- implementation. 
-% 
-% quicksort ​ 
-% 
-qsort( []) = []. 
-qsort( [Hd | Tl]) = Result :- ( 
-        /* length 1 */ 
- Tl = [] -> Result = [Hd]  
-      ; 
-        /* length 2 */ 
- Tl = [Hd2] -> (  
-                   Hd =< Hd2 -> Result = [Hd | [Hd2]] ​ 
-                         ; 
-   Result = [Hd2 | [Hd]] 
-                 )  
-      ; 
- /* else */ 
-        InputList = [Hd | Tl], 
- Pivot = list.index0_det( InputList, list.length( InputList) / 2), 
- pivot_classify( InputList, Pivot, Lows, Mids, Highs), 
- Result = list.append( list.append( qsort(Lows),​ Mids), qsort(Highs)) 
- ). 
-% 
-% classify list elements 
-% 
-:- pred pivot_classify( list(int), int, list(int), list(int), list(int)). 
-:- mode pivot_classify( in, in, out, out, out) is det. 
-pivot_classify( [], _Pivot, [], [], []). 
-pivot_classify( [Hd | Tl], Pivot, Lows, Mids, Highs) :-  
-        ( Hd < Pivot -> some [Lows0] (  
-                          pivot_classify( Tl, Pivot, Lows0, Mids, Highs), 
-                          Lows = [Hd | Lows0] 
-                         ​) ​ 
-        ; 
-          Hd > Pivot -> some [Highs0] (  
-                          pivot_classify( Tl, Pivot, Lows, Mids, Highs0), 
-                          Highs = [Hd | Highs0] 
-                         ​) ​ 
-        ; 
-          /* else */ 
-          some [Mids0] ( 
-            pivot_classify( Tl, Pivot, Lows, Mids0, Highs), 
-            Mids = [Hd | Mids0] 
-          ) 
-        ). 
-:- end_module quicksort. 
-</​code>​ 
- 
- 
-==== Predykaty i funkcje ==== 
- 
-Składnia: 
-<​code>​ 
-:- pred is_all_uppercase(string). ​   
-:- func strlen(string) = int. 
-</​code>​ 
-Predykaty i funkcje w Mercurym mogą być również polimorficzne:​ 
-<​code>​ 
-:- pred member(T, list(T)). 
-:- func length(list(T)) = int. 
-</​code>​ 
- 
-Składnia Haskella jest podobna: 
-<code Haskell> 
-is_all_uppercase :: String -> Bool 
-is_all_uppercase [] = False 
-is_all_uppercase (a:[]) = isUpper a 
-is_all_uppercase (pierwszyZnak:​resztaZnakow) = isUpper pierwszyZnak && is_all_uppercase resztaZnakow 
- 
-length :: [t] -> Int 
-length [] = 0 
-length (x:xs) = 1 + lenght xs 
- 
-map                     :: (a->b) -> [a] -> [b] 
-map f  []               ​= ​ [] 
-map f (x:​xs) ​           =  f x : map f xs 
-</​code>​ 
- 
-W Mercurym funkcje i predykaty to również wyrażenia. Predykaty i funkcje jako argumenty mogą przyjmować inne predykaty i funkcje. 
-Poniżej przedstawione są predykaty i funkcje wyższych rzędów. ​ 
-<​code>​ 
-:- type foldl_pred(T,​ U) == pred(T, U, U). 
-:- type foldl_func(T,​ U) == (func(T, U) = U). 
-      
-:- pred p(int) `with_type` foldl_pred(T,​ U). 
-:- func f(int) `with_type` foldl_func(T,​ U). 
- 
-% co jest równoważne 
-% :- pred p(int, T, U, U). 
-% :- pred f(int, T, U) = U. 
-% lub 
-% :- pred p(int, foldl_pred(T,​ U)). 
-% :- pred f(int, foldl_func(T,​ U)) = U. 
-</​code>​ 
- 
- 
- 
-==== System instancji (ang. instantiatedness) ==== 
- 
-**System instancji** pozwala zdefiniować __stan instancji__ danego __typu__. 
- 
-Każdy typ jest opisany za pomocą drzewa. Drzewo to składa się z konstruktorów typu (__or node__) i argumentów tych konstruktorów (__and node__). System instancji pozwala na opis argumentów konstruktorów (__and node__) danego typu. 
- 
- 
-| {{  :​pl:​miw:​2009:​miw09_mercury:​drzewo_typu_i_instancji.png ​ }} | 
-|  **Typ i instancja** ​ | 
- 
-Podstawowymi blokami budującymi system instancji w Merkurym są stany: 
- 
-**niezwiązany (ang. free)**, czyli zmiennej nie jest przypisana żadna wartość ani wyrażenie (w C++ deklaracja zmiennej jakiejś klasy bez inicjalizacji np.: ''​String lancuch;''​ wtedy zmienna //lancuch// byłaby niezwiązana),​ a dodatkowo zmienna ta nie jest związana z żadną inną zmienną. Wszyscy potomkowie niezwiązanego argumentu (and node) są niezwiązani,  ​ 
- 
-**związany (ang. bound)**, czyli zmiennej jest przypisana jakaś wartość lub wyrażenie (np. w C++ ''​String zwiazanyLancuch = "​miw";''​) 
- 
- 
-Z ich pomocą można budować bardziej wyszukane stany instancji. Poniżej znajduje się przykład stanu instancji "​dbOperationInst"​ dla typu "​dbOperation":​ 
- 
-<​code>​ 
-:- type dbOperation ---> lookup(key, data) ; set(key, data). 
- 
-:- inst dbOperationInst ---> lookup(ground,​ free) ; set(ground, ground). 
- 
-</​code>​ 
- 
- 
-==== System trybów (ang. mode system)==== 
-System trybów (ang. //mode system//), ogólnie rzecz biorąc, pozwala narzucić **ograniczenie** na zmianę stanu instancji zmiennej. Tryb funkcji lub predykatu jest mapowaniem pomiędzy początkowym stanem instancji argumentów i rezultatu (predykatu lub funkcji), a ich końcowym stanem instancji. 
- 
-Np. jeżeli chcemy nałożyć ograniczenia na argumenty wejściowe funkcji i jej rezultat, to ograniczenia te możemy zdefiniować w następujący sposób: ​ 
- 
-<​code>​ 
-:- mode in(Inst) == Inst >> Inst.            /* definicja trybu parametrycznego */ 
-:- mode out(Inst) == free >> Inst.           /* definicja trybu parametrycznego */ 
-:- inst listskel ---> []; [free | listskel]. 
- 
-:- func length(list(T)) = int.               /* deklatacja funkcji */ 
-:- mode length(in(Inst =< listskel)) = out.  /* definicja parametrycznie ograniczonego trybu funkcji */ 
-:- mode length(out(Inst =< listskel)) = in.  /* definicja parametrycznie ograniczonego trybu funkcji */ 
-</​code>​ 
- 
-Definicja trybu może zawierać argument parametryczny,​ w powyższym przykładzie parametrem tym jest "​Inst"​. 
- 
- 
-<​code>​ 
-:- pred append(list(T),​ list(T), list(T)). ​ /* deklatacja predykatu */ 
-:- mode append(in, in, out) is det.         /* definicja trybu predykatu */ 
-:- mode append(in, out, in) is semidet. ​    /* definicja trybu predykatu */ 
-:- mode append(out, in, in) is semidet. ​    /* definicja trybu predykatu */ 
-:- mode append(out, out, in) is multi. ​     /* deklatacja predykatu */ 
- 
-% definicja predykatu 
-append(Xs, Ys, Zs) :-  
-  (  
-    Xs = [], 
-    Zs = Ys 
-  ; 
-    Xs = [Hd | Tl], 
-    append(Tl, Ys, Zs0), 
-    Zs = [Hd | Zs0] 
-  ). 
-</​code>​ 
- 
-=== Unique insts and modes === 
-Deklaracje trybów mogą również opisywać tak zwane "tryby unikatowe"​. Tryby unikatowe w Mercury'​m są podobne do "​typów liniowych"​ występujących w niektórych funkcjonalnych językach programowania jak na przykład Clean. Można za ich pomocą oznaczyć zmienną jako taką do której istnieje tylko jedno odniesienie. Tryby unikatowe są używane do optymalizacji kompilowanego kodu (np. destrukcyjne przypisanie jednego elementu tablicy, zamiast kopiowanie całej tablicy żeby zmienić element) oraz jako mechanizm, który jest używany przez Mercury'​ego w celu stworzenia deklaratywnych operacji I/O. 
- 
-Wbudowane stany unikatowych instancji: 
- 
-   ​* ​ unique - takie same jak ground z tym, że istnieje dodatkowe ograniczenie mówiące że istnieje tylko jedno odwołanie do odpowiadającej wartości wyrażenia 
-   * unique(...) - pozwala na budowanie drzewa 
-   * dead - nie ma żadnego odniesienia do odpowiadającej wartości wyrażenia 
- 
-<​code>​ 
-     % unique output 
-     :- mode uo == free >> unique. 
-      
-     % unique input 
-     :- mode ui == unique >> unique. 
-      
-     % destructive input 
-     :- mode di == unique >> dead. 
-</​code>​ 
- 
-==== Determinizm ==== 
- 
-Dla każdego trybu (//mode//) funkcji i predykatu w Mercury'​m,​ definiujemy ile udanych rozwiązań może posiadać ten tryb, oraz czy znalezienie pierwszego rozwiązania może nie powieść się, czy też nie. 
- 
-W zależności od możliwości niepowodzenia znalezienia rozwiązania oraz ilości możliwych rozwiązań,​ w tabeli poniżej zostały przedstawione wszystkie możliwe kategorie determinizmu. 
- 
- 
-|                ^ 0 solution ​    ^ 1  solution ​   ^ more than 1 solution ^ 
-^ can't fail     ​| ​  ​erroneous ​   |       ​det ​     |     ​multi ​    | 
-^ can fail       ​| ​   failure ​    ​| ​    ​semidet ​   |     ​nondet ​   | 
- 
- 
-Ze względu na wiedzę kompilatora na temat ilości rozwiązań danej procedury poniżej przedstawione zostało drzewo zależności pomiędzy poszczególnymi kategoriami determinizmu:​ 
- 
-                  erroneous 
-                   / ​    \ 
-               ​failure ​  det 
-                  \     / ​  \ 
-                  semidet ​ multi 
-                      \     / 
-                       ​nondet 
- 
-Składnia determinizmu w Mercurym jest przedstawiona na przykładzie poniżej: 
-<​code>​ 
-     :- pred append(list(T),​ list(T), list(T)). 
-     :- mode append(in, in, out) is det. 
-     :- mode append(out, out, in) is multi. 
-     :- mode append(in, in, in) is semidet. 
-      
-     :- func length(list(T)) = int. 
-     :- mode length(in) = out is det. 
-     :- mode length(in(list_skel)) = out is det. 
-     :- mode length(in) = in is semidet. 
-</​code>​ 
- 
- 
- 
-==== Funkcje i predykaty wyższych rzędów ==== 
- 
-Mercury pozwala na programowanie funkcji i predykatów wyższych rzędów, w szczególności dostępne są: 
-  * zwijanie (//ang. currying//) - %%f(x,y) = x/y%%, %%f(2/3) = g(3) (g(y) = 2/y) = 2/3%% 
-  * klauzule (//ang. closures//) - czyli funkcje, która używają wolnych zmiennych(zmienna,​ która nie jest związana: Haskell %%/x -> x y%% -> y jest wolną zmienną), "​otaczające"​ jakąś przestrzeń leksykalną,​ np. Haskell %%f x = (\y -> x + y)%% w tym przypadku f zwraca klauzulę, ponieważ zmienna x, która jest przypisana na zewnątrz lambda abstrakcji, jest używana wewnątrz niej. 
-  * funkcje anonimowe (//ang. lambda abstractions//​) np. Haskell %%f x = (\y -> x + y)%% 
- 
-Weźmy następujący predykat w Mercurym: 
-<​code>​ 
-     :- pred sum(list(int),​ int). 
-     :- mode sum(in, out) is det. 
-</​code>​ 
- 
-Możemy go użyć w następujący sposób: 
-<​code>​ 
-     :- func scalar_product(int,​ list(int)) = list(int). 
-     :- mode scalar_product(in,​ in) = out is det. 
- 
-     X = (func(Num::​in,​ List::in) = (NewList::​out) is det 
-             :- NewList = scalar_product(Num,​ List)), 
-     ​sum(X,​ 2). 
-</​code>​ 
- 
-=== Zwijanie (currying) === 
- 
-<​code>​ 
-     ​Sum123 = sum([1,​2,​3]) 
- 
-% binds `Sum123'​ to a higher-order predicate term of type `pred(int)'​. 
-</​code>​ 
- 
-*Ograniczenia* 
-nie można używać nazw operacji wbudowanych w język, np. zamiast 
-<​code>​ 
-list.filter(\=(2),​ [1, 2, 3], List) 
-</​code>​ 
- 
-należy użyć: 
-<​code>​ 
-list.filter((pred(X::​in) is semidet :- X \= 2), [1, 2, 3], List) 
- 
-%lub 
-     ​list.filter(not_equal(2),​ [1, 2, 3], List) 
- 
-%gdzie not_equal jest zdefiniowane nastepujaco 
-     :- pred not_equal(T::​in,​ T::in) is semidet. 
-          not_equal(X,​ Y) :- X \= Y. 
-</​code>​ 
- 
- 
- 
-=== Klauzule (closures) === 
- 
-<​code>​ 
-     ​addNumFunction = (func addNumbers(X::​in,​ Y::in) = Sum::out is Det :- Sum = X + Y). 
- 
-     :- func sum2Nums(int::​in,​ int::in) = int::out. 
- 
-     :- func addNumClosure(X::​in) = PartialSum::​out :- 
-         ​%PartialSum = call(addNumFunction,​ X).  
-          PartialSum = sum2Nums(X). 
- 
-</​code>​ 
- 
- 
-==== Moduły i ukrywanie implementacji ==== 
-Merkury wspiera modularny sposób budowania programów, pozwala również na ukrywanie szczegółów implementacyjnych. 
-Poniżej przedstawiono przykładowy moduł: 
-<​code>​ 
-     :- module ModuleName. 
- 
-     :- interface. 
- 
-     % moduly importowane 
-     :- include_module ModuleToInclude. 
- 
-     % 
-     % przedmioty eksportowane prze modul 
-     % 
- 
-     :- implementation. 
- 
-     % prywatne moduly potrzebne do implementacji 
-     :- include_module PrivateModuleToInclude. 
- 
-     % 
-     % szczegoly implementacji 
-     % 
- 
-     :- end_module ModuleName. 
-</​code>​ 
- 
-Każdy moduł zaczyna się od deklaracji ​ 
-<​code>:​- module ModuleName.</​code>​ 
-gdzie "​ModuleName"​ to nazwa modułu. 
- 
-Deklaracja interfejsu modułu zaczyna się od: 
-<​code>:​- interface.</​code>​ 
-Sekcja ta specyfikuje,​ które przedmioty są eksportowane przez ten moduł. 
- 
-Deklaracja części implementacyjnej modułu jest następująca:​ 
-<​code>:​- implementation.</​code>​ 
-Sekcja ta zawiera implementację wszystkich przedmiotów. Sekcja ta jest prywatna dla modułu. 
- 
-Koniec modułu jest oznaczany deklaracją:​ 
-<​code>:​- end_module ModuleName.</​code>​ 
-gdzie "​ModuleName"​ to nazwa modułu. 
- 
-Aby importować moduły umieszczone w oddzielnych plikach należy posłużyć się deklaracją:​ 
-<​code>:​- include_module Module.Module1,​ Module2, ModuleN</​code>​ 
-Nazwy tych plików muszą być związane z nazwą modułu, dla przykładu jeżeli importujemy moduł o nazwie "​Module.Module1"​ to plik zawierający ten moduł musi mieć nazwę "​Module.Module1.m"​. __Nazwy modułów muszą być pełne (//ang. fully qualified//​)__. ​ 
- 
-Każda deklaracja w module rodzicu jest widoczna w module dziecku, ale nie na odwrót. 
- 
- 
-==== Type classes ==== 
-Merkury wspiera ograniczony polimorfizm za pomocą klas typów (//ang. type classes//). Klasy typów pozwalają pisać predykaty i funkcje, które operują na zmiennych dowolnego typu, dla których pewien zbiór operacji jest zdefiniowany. Klasy typów są podobne do interfejsów w Javie, a w Haskell'​u do Type Classes. 
- 
-Przykład klasy typu w Mercury'​m:​ 
-<​code>​ 
-     :- typeclass point(T) where [ 
-             % coords(Point,​ X, Y): 
-             ​% ​      X and Y are the cartesian coordinates of Point 
-             pred coords(T, float, float), 
-             mode coords(in, out, out) is det, 
-      
-             % translate(Point,​ X_Offset, Y_Offset) = NewPoint: 
-             ​% ​      ​NewPoint is Point translated X_Offset units in the X direction 
-             ​% ​      and Y_Offset units in the Y direction 
-             func translate(T,​ float, float) = T 
-     ]. 
-</​code>​ 
-Liczba parametrów klasy typów jest nie ograniczona:​ 
-<​code>:​- typeclass a(T1, T2) where [...].</​code>​ 
- 
- 
-<​code>​ 
-:- type coordinate 
-             ​--->​ coordinate( 
-                     ​float, ​          % X coordinate 
-                     ​float ​           % Y coordinate 
-             ). 
-      
-     :- instance point(coordinate) where [ 
-             ​pred(coords/​3) is coordinate_coords,​ 
-             ​func(translate/​3) is coordinate_translate 
-     ]. 
-      
-      
-     :- pred coordinate_coords(coordinate,​ float, float). 
-     :- mode coordinate_coords(in,​ out, out) is det. 
-      
-     ​coordinate_coords(coordinate(X,​ Y), X, Y). 
-      
-     :- func coordinate_translate(coordinate,​ float, float) = coordinate. 
-      
-     ​coordinate_translate(coordinate(X,​ Y), Dx, Dy) = coordinate(X + Dx, Y + Dy). 
-</​code>​ 
- 
- 
-<​code>​ 
-     :- type rgb 
-             ​--->​ rgb( 
-                     int, 
-                     int, 
-                     int 
-             ). 
-      
-     :- type coloured_coordinate 
-             ​--->​ coloured_coordinate( 
-                     ​float,​ 
-                     ​float,​ 
-                     rgb 
-             ). 
-      
-     :- instance point(coloured_coordinate) where [ 
-             ​pred(coords/​3) is coloured_coordinate_coords,​ 
-             ​func(translate/​3) is coloured_coordinate_translate 
-     ]. 
-      
-      
-     :- pred coloured_coordinate_coords(coloured_coordinate,​ float, float). 
-     :- mode coloured_coordinate_coords(in,​ out, out) is det. 
-      
-     ​coloured_coordinate_coords(coloured_coordinate(X,​ Y, _), X, Y). 
-      
-     :- func coloured_coordinate_translate(coloured_coordinate,​ float, float) 
-             = coloured_coordinate. 
-      
-     ​coloured_coordinate_translate(coloured_coordinate(X,​ Y, Colour), Dx, Dy) 
-             = coloured_coordinate(X + Dx, Y + Dy, Colour). 
-</​code>​ 
- 
-=== Ograniczenia klas typów dla funkcji i predykatów === 
- 
-<​code>​ 
-     :- pred distance(P1,​ P2, float) <= (point(P1), point(P2)). 
-     :- mode distance(in,​ in, out) is det. 
-      
-     ​distance(A,​ B, Distance) :- 
-             ​coords(A,​ Xa, Ya), 
-             ​coords(B,​ Xb, Yb), 
-             XDist = Xa - Xb, 
-             YDist = Ya - Yb, 
-             ​Distance = sqrt(XDist*XDist + YDist*YDist). 
-</​code>​ 
- 
-==== Existential types ==== 
- 
-Existentially quantified type variables (or simply "​existential types" for short) are useful tools for data abstraction. In combination with type classes, they allow you to write code in an "​object oriented"​ style that is similar to the use of interfaces in Java or abstract base classes in Cpp. 
- 
-Mercury supports existential type quantifiers on predicate and function declarations,​ and in data type definitions. You can put type class constraints on existentially quantified type variables. ​ 
- 
- 
- 
-===== Cechy języków Haskell i Mercury ===== 
-Sztandarowe cechy języków, standardowe biblioteki, narzędzia programistyczne 
-==== Purity ==== 
-==== Laiziness - Strictness ==== 
-==== Type system ==== 
-==== Module system ==== 
-==== Standard librarnies ==== 
-==== Tools, extensions ==== 
-==== Extensibility ==== 
- 
-===== Referencje ===== 
- 
- 
-====== Prezentacja ====== 
-====== Materiały ====== 
- 
- 
- 
- 
- 
- 
  
pl/miw/2009/miw09_mercury.1251048205.txt.gz · ostatnio zmienione: 2019/06/27 15:57 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0