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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Wkm (dyskusja | edycje)
Wkm (dyskusja | edycje)
 
(Nie pokazano 2 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 40: Linia 40:
Rozważmy zatem inny wariant sprawdzania pustości listy. Wykorzystajmy funkcję, która wylicza długość listy:
Rozważmy zatem inny wariant sprawdzania pustości listy. Wykorzystajmy funkcję, która wylicza długość listy:


   ''pusta2 :: [a] -> Bool
   pusta2 :: [a] -> Bool
   pusta2 x = (dl x == 0)''
   pusta2 x = (dl x == 0)


Ta definicja jest poprawna, ma jednak poważną wadę. Jaką? Jak ją wyeliminować, tzn. jak napisać dobrą funkcję sprawdzającą pustość listy?
Ta definicja jest poprawna, ma jednak poważną wadę. Jaką? Jak ją wyeliminować, tzn. jak napisać dobrą funkcję sprawdzającą pustość listy?
Linia 47: Linia 47:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Sprawdzenie pustości listy jest tu poprzedzone wyliczeniem jej długości — a to przecież jest strata czasu. Co gorsza, takie sprawdzenie nie zadziała dla list nieskończonych, np. [1..]. Dobra funkcja może wyglądać jak poniżej; nie czynimy tu żadnych założeń o typie a ani nie liczymy długości listy.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Sprawdzenie pustości listy jest tu poprzedzone wyliczeniem jej długości — a to przecież jest strata czasu. Co gorsza, takie sprawdzenie nie zadziała dla list nieskończonych, np. [1..]. Dobra funkcja może wyglądać jak poniżej; nie czynimy tu żadnych założeń o typie a ani nie liczymy długości listy.


   ''pusta3 :: [a] -> Bool
   pusta3 :: [a] -> Bool
   pusta3 [] = True
   pusta3 [] = True
   pusta3 (_:_) = False''
   pusta3 (_:_) = False


</div></div>
</div></div>
Linia 64: Linia 64:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> To jest proste:
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> To jest proste:


   ''połącz :: [[a]] -> [a]
   połącz :: <nowiki>[[a]]</nowiki> -> [a]
   połącz [] = []
   połącz [] = []
   połącz (x:xs) = x ++ połącz xs''
   połącz (x:xs) = x ++ połącz xs


</div></div>
</div></div>
===Zadanie 7===
===Zadanie 7===
Przy funkcji połącz zdefiniowanej tak jak w poprzednim zadaniu, które wywołania są poprawne?
Przy funkcji połącz zdefiniowanej tak jak w poprzednim zadaniu, które wywołania są poprawne?


* połącz [[[]]]
* połącz <nowiki>[[[]]]</nowiki>
* połącz [[1, 2], [], [3]]
* połącz <nowiki>[[1, 2], [], [3]]</nowiki>
* połącz [[[1, 2]], [], [[3]]]
* połącz <nowiki>[[[1, 2]], [], [[3]]]</nowiki>
* połącz [[[1, 2]], [[]], [[3]]]
* połącz <nowiki>[[[1, 2]], [[]], [[3]]]</nowiki>
* połącz [[], [[]], [[[]]]]
* połącz <nowiki>[[], [[]], [[[]]]]</nowiki>
* połącz [[1], [[2]], [[[3]]]]
* połącz <nowiki>[[1], [[2]], [[[3]]]]</nowiki>


<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wszystkie z wyjątkiem ostatniego. We wszystkich bowiem przypadkach poza ostatnim Haskell jest w stanie dobrać taki typ a, żeby uzyskać zgodny z sygnaturą typ parametru [[a]]. Przykładowo, w dwóch środkowych wywołaniach a to [Integer]. Pouczające jest obejrzenie wyników wszystkich tych wywołań...
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wszystkie z wyjątkiem ostatniego. We wszystkich bowiem przypadkach poza ostatnim Haskell jest w stanie dobrać taki typ a, żeby uzyskać zgodny z sygnaturą typ parametru <nowiki>[[a]]</nowiki>. Przykładowo, w dwóch środkowych wywołaniach a to [Integer]. Pouczające jest obejrzenie wyników wszystkich tych wywołań...
</div></div>
</div></div>

Aktualna wersja na dzień 22:00, 23 wrz 2006

Zadanie 1

Zdefiniować odejmowanie dla typu Nat w dwóch wariantach: zupełnym i częściowym. W pierwszym odjęcie większej liczby od mniejszej ma dawać zero. W drugim wartość taka ma być niezdefiniowana. Co się stanie, jeśli spróbujemy jednak odjąć większą liczbę od mniejszej?

Wskazówka:

Zadanie 2

Zdefiniować silnię jako stosowną aplikację funkcji rekdef.

Wskazówka:

Zadanie 3*

Poniższa funkcja ma sprawdzać, czy podana lista jest pusta. Dlaczego definicja ta jest niepoprawna?

 pusta1 :: [a] -> Bool
 pusta1 x = (x == [])
Wskazówka:

Zadanie 4

Rozważmy zatem inny wariant sprawdzania pustości listy. Wykorzystajmy funkcję, która wylicza długość listy:

 pusta2 :: [a] -> Bool
 pusta2 x = (dl x == 0)

Ta definicja jest poprawna, ma jednak poważną wadę. Jaką? Jak ją wyeliminować, tzn. jak napisać dobrą funkcję sprawdzającą pustość listy?

Wskazówka:

Zadanie 5

Napisać funkcję, która zwraca ostatni element niepustej listy. Funkcja powinna działać dla list dowolnego typu, bez jakichkolwiek dodatkowych założeń.

Wskazówka:

Zadanie 6

Zdefiniować funkcję połącz, która połączy listę list w jedną listę. Przykładowo, połącz [[1, 2], [3, 4, 5], [6]] ma dać wynik [1, 2, 3, 4, 5, 6].

Wskazówka:

Zadanie 7

Przy funkcji połącz zdefiniowanej tak jak w poprzednim zadaniu, które wywołania są poprawne?

  • połącz [[[]]]
  • połącz [[1, 2], [], [3]]
  • połącz [[[1, 2]], [], [[3]]]
  • połącz [[[1, 2]], [[]], [[3]]]
  • połącz [[], [[]], [[[]]]]
  • połącz [[1], [[2]], [[[3]]]]
Wskazówka: