Liczby z listy podzielne przez 3

Liczby z listy podzielne przez 3
  • Rejestracja: dni
  • Ostatnio: dni
0

Witam mam trochę trudności z haskellem dlatego proszę o pomoc.
Chciałem zrobić następujące zadanie, napisac dunckce podzielnePrzez3 z sygnatura ktora dla przekazanej listy ma zwrocic liste liczb podzielnych przez 3.

no wiec na poczatku musze podac typ danych, wiec wrowadzam liste i otrzymuje liste
podzielPrzez3 :: [a]->[a]
i na razie moje zalozenie jest takie ze podaje liste i jezeli element listy jest mod 3 = 0 to wypisuje go

podzielPrzez3 [a] = if a mod 3 then a

oczywiscie to nie dziala :) nawet sie nie kompiluje, czy ktos na spokojnie moze mi wskazac blad i pomoc z tym zadaniem.

  • Rejestracja: dni
  • Ostatnio: dni
0

Błędów od cholery i ciut ciut:

  1. Haskell jest silnie typowany, nie ma automatycznej konwersji Int -> Bool
  2. if wymaga else zawsze, każde wyrażenie musi coś produkować
  3. przetwarzasz listę, zapisałeś pattern na listę z pojedynczym elementem
  4. używasz funkcji jako operatora, bez notacji infiksowej

Najpierw przypadek bazowy:

Kopiuj
podzielnePrzez3 [] = [] -- dla pustej listy nie robimy nic

następne właściwy krok, aktualnie z if, dekompozycja listy, jeżeli podzielne to osadzamy element i wynik filtracji reszty, w przeciwnym wypadku wyłącznie resztę.

Kopiuj
podzielnePrzez3 (x:xs) = if x `mod` 3 == 0 then x : podzielnePrzez3 xs else podzielnePrzez3 xs

całość można zapisać z pattern guardem:

Kopiuj
podzielnePrzez3 (x:xs) | x `mod` 3 == 0 = x : podzielnePrzez3 xs
                       | otherwise      = podzielnePrzez3 xs

Tylko po co się rozdrabniać?

Kopiuj
podzielnePrzez3 = filter $ \n -> n `mod` 3 == 0
-- ew. w point-free
podzielnePrzez3 = filter ((== 0) . (`mod` 3))
  • Rejestracja: dni
  • Ostatnio: dni
0

Inny wariant to wykorzystanie list-comprehension:

Kopiuj
podzielnePrzez3 xs = [ x | x <- xs, x `mod` 3 == 0 ]

lub fakt, że lista jest monadą:

Kopiuj
podzielnePrzez3 xs = do x <- xs; guard $ x `mod` 3 == 0; return x
  • Rejestracja: dni
  • Ostatnio: dni
0

Dzięki wielkie za wytłumaczenie!

Niby coś zaczyna świtać, mam mały problem ze zrozumieniem tego zapisu (x:xs).

  • Rejestracja: dni
  • Ostatnio: dni
0

: to konstruktor listy (cons), po lewej stronie element, po prawej ogon. Konstruktory używa się do konstruowania obiektów jak i ich "dekonstrukcji" z użyciem pattern matchingu, x:xs jako argument funkcji oznacza "głowę listy nazwiemy x, ogon xs". Zapis listy w formie [1, 2, 3, 4] jest równoważny 1 : 2 : 3 : 4 : []. Powinieneś przerobić chociaż jakiś tutorial, np. http://learnyouahaskell.com/, względnie kompletny i pisany "idiotoodpornie".

  • Rejestracja: dni
  • Ostatnio: dni
0

Dzięki wielkie, tutorial bardzo fajny. Mam małe problemy z deklaracją typów.

teraz moje zadanie polega na porownaniu dwoch wrpowadzonych list, jezeli sa identyczen to komunikat true jezeli nie to false.
Sprawdzenie list napisalem tyle ze nie wiem jak teraz napisac deklaracje typow tak zeby zwrocic Bool.

Kopiuj
 czyRozne []_= []
czyRozne _[]= []
czyRozne (x:xs) (y:ys) = if x==y  then (x,y) : czyRozne xs ys else czyRozne xs ys
hauleth
  • Rejestracja: dni
  • Ostatnio: dni
0
Kopiuj
czyRozne _ [] = true
czyRozne [] _ = true
czyRozne (x:xs) (y:ys) = if x == y then czyRozne xs xy else false
  • Rejestracja: dni
  • Ostatnio: dni
0

Hmm wyglada rozsadnie :P ale bez opisu typu funkcji nie chce ruszyc.
Wydaje mi sie ze bedzie podobny do tego

czyRozne ::[a]->[b]->Bool

No ale ten jest błędny

  • Rejestracja: dni
  • Ostatnio: dni
0

Nie wygląda rozsądnie bo winnerfresh nie rozumie chyba ani konstruktorów typów, ani rekurencji. Zapisane w czytelniejszej formie, z użyciem pattern guardów:

Kopiuj
czyRozne _ [] = True
czyRozne [] _ = True
czyRozne (x:xs) (y:ys) | x == y    = czyRozne xs xs
                       | otherwise = False

Warunek jest najzwyczajniej w świecie błędny, powinien być przeciwny (/=), "kontynuuj póki pary elementów trzymają własność". Po prawidłowym użyciu Boola inferencja typów sama sobie poradzi, jak w większości wypadków nie ma potrzeby pisać sygnatur.

Kopiuj
czyRozne ::[a]->[b]->Bool

Jest błędne, nie porównujesz elementów różnych typów, dodatkowo muszą one być porównywalne, być instancjami Eq. Całość w prawidłowej formie przedstawia się następująco:

Kopiuj
czyRozne :: Eq a => [a] -> [a] -> Bool -- zbędna, z kodu zostanie wywynioskowana identyczna
czyRozne _ [] = True
czyRozne [] _ = True
czyRozne (x:xs) (y:ys) | x /= y    = czyRozne xs ys
                       | otherwise = False

Tylko po co się rozdrabniać? Można np. tak:

Kopiuj
czyRozne1 xs ys = all id $ zipWith (/=) xs ys
czyRozne2 xs ys = False `notElem` zipWith (/=) xs ys
hauleth
  • Rejestracja: dni
  • Ostatnio: dni
0

Pisałem z palca. Nie chciało mi się myśleć ani testować ;P

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.