Paradygmaty programowania/Ćwiczenia 10: Programowanie funkcyjne w Haskellu I: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Wkm (dyskusja | edycje)
Wkm (dyskusja | edycje)
 
(Nie pokazano 3 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 28: Linia 28:
Która z poniższych funkcji nie jest jednoargumentowa?
Która z poniższych funkcji nie jest jednoargumentowa?


      (+2), (–7), (*5), (/2), (3/), (<1), (`div` 3), (100 `div`)
(+2), (–7), (*5), (/2), (3/), (<1), (`div` 3), (100 `div`)


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wyjątkowo traktowany jest minus, w związku z czym (–7) jest traktowane nie jako jednoargumentowa funkcja odejmująca 7, lecz po prostu jako liczba –7.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wyjątkowo traktowany jest minus, w związku z czym (–7) jest traktowane nie jako jednoargumentowa funkcja odejmująca 7, lecz po prostu jako liczba –7.
Linia 44: Linia 44:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Argument funkcji error to napis (typ String), natomiast wynik musi pasować do dowolnego kontekstu — jest to zatem niczym nie ograniczony typ polimorficzny, wyrażony zmienną typową bez klauzuli ograniczającej zakres. Summa summarum:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Argument funkcji error to napis (typ String), natomiast wynik musi pasować do dowolnego kontekstu — jest to zatem niczym nie ograniczony typ polimorficzny, wyrażony zmienną typową bez klauzuli ograniczającej zakres. Summa summarum:


  ''error :: String -> a''
  error :: String -> a
</div></div>
</div></div>


Linia 50: Linia 50:
Postawmy definicję:
Postawmy definicję:


  ''para :: Num a => a -> (a, a)
  para :: Num a => a -> (a, a)
  para x = (x, x)''
  para x = (x, x)


Funkcję podnoszącą do kwadratu można teraz wyrazić jako złożenie powyższej funkcji tworzącej parę z mnożeniem. Czy zatem poniższa definicja jest poprawna? Jeśli nie, to co należy zmienić?
Funkcję podnoszącą do kwadratu można teraz wyrazić jako złożenie powyższej funkcji tworzącej parę z mnożeniem. Czy zatem poniższa definicja jest poprawna? Jeśli nie, to co należy zmienić?


  ''kw :: Num a => a -> a
  kw :: Num a => a -> a
  kw = (*) . para''
  kw = (*) . para


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Problem w tym, że zwykły operator mnożenia (sama gwiazdka) wymaga zapisu infiksowego, zaś (*) to postać rozwinięta. Tu natomiast potrzebne jest mnożenie w postaci zwykłej funkcji dwuargumentowej. Trzeba zatem „zwinąć” funkcję (*), pisząc:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Problem w tym, że zwykły operator mnożenia (sama gwiazdka) wymaga zapisu infiksowego, zaś (*) to postać rozwinięta. Tu natomiast potrzebne jest mnożenie w postaci zwykłej funkcji dwuargumentowej. Trzeba zatem „zwinąć” funkcję (*), pisząc:


  ''kw = uncurry (*) . para''
  kw = uncurry (*) . para
</div></div>
</div></div>


===Zadanie 8===
===Zadanie 8===
Napisz funkcję ppd<math>(n, x)</math>, która podnosi <math>x </math> do potęgi <math>2^n </math>. Zwróć uwagę zarówno na efektywność, jak i na przejrzystość definicji.
Napisz funkcję ppd(n, x), która podnosi x do potęgi <math>2^n</math>. Zwróć uwagę zarówno na efektywność, jak i na przejrzystość definicji.


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Podnoszenie do potęgi dwójki pozwala napisać szczególnie urodziwą funkcję... Korzystając z wcześniej zdefiniowanych funkcji możemy napisać:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Podnoszenie do potęgi dwójki pozwala napisać szczególnie urodziwą funkcję... Korzystając z wcześniej zdefiniowanych funkcji możemy napisać:


  ''ppd :: Num a => (Integer, a) -> a
  ppd :: Num a => (Integer, a) -> a
  ppd (n, x) = iter (n, kw) x''
  ppd (n, x) = iter (n, kw) x


Decydując się na wariant rozwinięty, moglibyśmy zapisać „jeszcze bardziej funkcyjną” definicję:
Decydując się na wariant rozwinięty, moglibyśmy zapisać „jeszcze bardziej funkcyjną” definicję:


  ''ppdr :: Num a => Integer -> a -> a
  ppdr :: Num a => Integer -> a -> a
  ppdr n = iter (n, kw)''
  ppdr n = iter (n, kw)
</div></div>
</div></div>

Aktualna wersja na dzień 21:35, 23 wrz 2006

Zadanie 1

Zdefiniuj na dwa sposoby funkcję, która do danej liczby całkowitej dodaje 5.

Wskazówka:

Zadanie 2

Przypomnijmy definicję funkcji mnożącej dwie liczby:

mnóż :: (Integer, Integer) -> Integer
mnóż (x, y) = if x == 0 || y == 0 then 0 else x * y

Czy poniższy wariant byłby lepszy pod względem wykorzystania mechanizmu obliczania leniwego (tzn. który argument i kiedy nie będzie obliczany)?

mnóż (x, y) = if x == 0 then 0 else x * y

Zadanie 3

Która z poniższych funkcji nie jest jednoargumentowa?

(+2), (–7), (*5), (/2), (3/), (<1), (`div` 3), (100 `div`)
Wskazówka:

Zadanie 4

Napisz kilka wariantów „klasycznej funkcji dydaktycznej”, czyli silni. Zadbaj o obsługę błędnych argumentów. Haskell zawiera standardową funkcję error, która powoduje zerwanie obliczeń i wyświetlenie komunikatu o błędzie. Funkcja error bierze jeden argument napisowy. Zwróć uwagę, że aby wywołać funkcję z argumentem ujemnym, trzeba go ująć w nawiasy (w przeciwnym razie minus w wywołaniu np. silnia –2 zostanie uznany za operator dwuargumentowy i dostaniemy komunikat o błędzie, ale nie tym, o którym mówimy...).

Zadanie 5*

Zastanów się (ponownie...) nad obliczaniem wyrazów ciągu Fibonacciego. Z oczywistych powodów prosta funkcja, odzwierciedlająca rekurencyjną definicję, jest nieefektywna. Czy wiesz już, jak napisać lepszą?

Zadanie 6

Zapisz nową wersję funkcji rkwadrat, która wylicza pierwiastki równania kwadratowego. Nowa wersja powinna zgłaszać błąd, jeśli równanie nie ma pierwiastków rzeczywistych. Jak sądzisz, jaka jest sygnatura funkcji error?

Wskazówka:

Zadanie 7

Postawmy definicję:

para :: Num a => a -> (a, a)
para x = (x, x)

Funkcję podnoszącą do kwadratu można teraz wyrazić jako złożenie powyższej funkcji tworzącej parę z mnożeniem. Czy zatem poniższa definicja jest poprawna? Jeśli nie, to co należy zmienić?

kw :: Num a => a -> a
kw = (*) . para
Wskazówka:

Zadanie 8

Napisz funkcję ppd(n, x), która podnosi x do potęgi 2n. Zwróć uwagę zarówno na efektywność, jak i na przejrzystość definicji.

Wskazówka: