Paradygmaty programowania/Ćwiczenia 12: Programowanie funkcyjne w Haskellu III: Różnice pomiędzy wersjami
(Nie pokazano 3 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
Linia 41: | Linia 41: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wystarczy zmienić definicję funkcji trójki tak, by generowała tylko trójki spełniające warunek x ≤ y ≤ z. Można to zrobić tak: | <div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wystarczy zmienić definicję funkcji trójki tak, by generowała tylko trójki spełniające warunek x ≤ y ≤ z. Można to zrobić tak: | ||
trójki :: Integer -> [(Integer, Integer, Integer)] | |||
trójki n = [(x,y,z) | x<-[1..n], y<-[x..n], z<-[y..n]] | trójki n = [(x,y,z) | x<-[1..n], y<-[x..n], z<-[y..n]] | ||
</div></div> | </div></div> | ||
===Zadanie 4=== | ===Zadanie 4=== | ||
Napisać funkcję lsilnia, która dla danego | Napisać funkcję lsilnia, która dla danego ''n'' ≥ 1 wygeneruje listę silni liczb od 1 do ''n''. Przykładowo, wywołanie lsilnia 4 ma dać listę [1, 2, 6, 24]. Jak zrobić to efektywnie? | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Oczywiście należy unikać liczenia silnia dla każdej liczby od początku. Można więc tak jak poniżej, z tym że trzeba wówczas na końcu odwrócić wytworzoną listę. | <div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Oczywiście należy unikać liczenia silnia dla każdej liczby od początku. Można więc tak jak poniżej, z tym że trzeba wówczas na końcu odwrócić wytworzoną listę. | ||
lsilnia :: Integer -> [Integer] | |||
lsilnia 1 = [1] | lsilnia 1 = [1] | ||
lsilnia (n+1) = ((n+1)*y) : y : ys where (y:ys) = lsilnia n | lsilnia (n+1) = ((n+1)*y) : y : ys where (y:ys) = lsilnia n | ||
</div></div> | </div></div> | ||
===Zadanie 5*=== | ===Zadanie 5*=== | ||
Zdefiniować operator >> za pomocą >>=. | Zdefiniować operator >> za pomocą >>=. | ||
Linia 60: | Linia 62: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wywołania p >> q oraz p >>= q oznaczają, że wywołujemy p i q w takiej właśnie kolejności. Dla operatora >>= ta zależność czasowa bierze się stąd, że q wywoływane jest z wartością wyliczoną przez p. Chcąc zdefiniować >>, musimy oprzeć się na tej samej zależności, lecz zignorować wyliczoną przez p wartość. | <div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Wywołania p >> q oraz p >>= q oznaczają, że wywołujemy p i q w takiej właśnie kolejności. Dla operatora >>= ta zależność czasowa bierze się stąd, że q wywoływane jest z wartością wyliczoną przez p. Chcąc zdefiniować >>, musimy oprzeć się na tej samej zależności, lecz zignorować wyliczoną przez p wartość. | ||
(>>) :: IO a -> IO b -> IO b | |||
p >> q = p >>= f where f x = q | p >> q = p >>= f where f x = q | ||
</div></div> | </div></div> | ||
===Zadanie 6=== | ===Zadanie 6=== | ||
Co się stanie przy poniższych wywołaniach? Sprawdź... | Co się stanie przy poniższych wywołaniach? Sprawdź... | ||
getChar >>= return | |||
return ’a’ >>= putChar | return ’a’ >>= putChar | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Można powiedzieć, że return zamienia wartość typu a na IO a, zaś >>= — na odwrót. | <div class="mw-collapsible mw-made=collapsible mw-collapsed">'''Wskazówka:''' <div class="mw-collapsible-content" style="display:none"> Można powiedzieć, że return zamienia wartość typu a na IO a, zaś >>= — na odwrót. | ||
</div></div> | </div></div> |
Aktualna wersja na dzień 22:49, 23 wrz 2006
Zadanie 1
Napisać definicję leniwego operatora alternatywy na liczbach całkowitych, nie korzystając ze standardowego operatora ||.
Zadanie 2
Zapisać za pomocą wyrażeń z kwalifikatorem listę trójek pitagorejskich (czyli liczb naturalnych takich, że ) z ustalonego zakresu. Chodzi zatem o funkcję o sygnaturze:
trójkipit :: Integer -> [(Integer, Integer, Integer)]
Dla danego n powinna ona stworzyć listę wszystkich trójek pitagorejskich, których elementy należą do przedziału [1...n].
Zadanie 3
Jak zmienić program z poprzedniego zadania, by nie wypisywał niepotrzebnie podobnych trójek, np. (3, 4, 5) i (4, 3, 5)?
Zadanie 4
Napisać funkcję lsilnia, która dla danego n ≥ 1 wygeneruje listę silni liczb od 1 do n. Przykładowo, wywołanie lsilnia 4 ma dać listę [1, 2, 6, 24]. Jak zrobić to efektywnie?
Zadanie 5*
Zdefiniować operator >> za pomocą >>=.
Zadanie 6
Co się stanie przy poniższych wywołaniach? Sprawdź...
getChar >>= return return ’a’ >>= putChar