2009-07-29 9 views
7

Próbuję uczyć się Haskell. Jedna rzecz, którą próbowałem zrobić, to napisać alternatywną funkcję, która zwróci ostatni element listy, powtarzając listę, aż ogon będzie pusty, a następnie zwróci głowę. Mam ...Wdrażanie ostatniej funkcji

mylast [] = [] 
mylast (x:[]) = x 
mylast (x:xs) = mylast xs 

... ale pojawia się błąd przy próbie dowolny niepusty listy :( Wszelkie sugestie co do tego, co zrobiłem źle? TIA.

+1

Należy przyjąć rtperson odpowiedź ... – yeyeyerman

Odpowiedz

8

Spróbuj mylast [] = error "Empty list!" . w przeciwnym razie zamiast Haskell nie można wywnioskować typ swojej funkcji

6

Efraim rozwiązanie powinno działać (up-głosowanie) Ale myślę, że to jest trochę bardziej „Haskell-like”..

mylast [] = Nothing 
mylast (x:[]) = Just x 
mylast (x:xs) = mylast xs 

Nota prawna: Tak naprawdę nie próbowałem tego. Być może popełniłem błędy składniowe.

+2

środkowa sprawa jest taka sama jak [ x], prawda? IOW, lista pojedynczych elementów utworzona przez konkatenację x z pustą listą "(x: [])" jest taka sama, jak lista zawierająca tylko x "[x]". Nie wiem, który z nich jest bardziej idiomatyczny. –

+0

Nie, tylko x nie jest takie samo jak [x]. –

+0

O, czekaj, rozumiem, co masz na myśli. Tak, środkowy przypadek to lista zawierająca tylko jeden znak x. Ale wszystkie listy mogą być wyrażone jako głowa i ogon, nawet jeśli jedno lub oba są puste. –

29

Problem - podobnie jak wiele innych, gdy uczysz się Haskell - jest jednym z pisania. Wpisz następujące polecenie w GHCi

:t mylast 

, a zobaczysz, że podpis typ jest

mylast :: [[a]] -> [a] 

który oczekuje listę list i zwróci listę. Więc jeśli umieścisz listę łańcuchów ["bob", "ogrodzenie", "dom"] funkcja zadziała tak, jak ją napisałeś.

Problem to Twój podstawowy przypadek: mylast [] = [], który mówi kompilatorowi, że chcesz zwrócić listę. Chcesz zwrócić element, a nie listę. Ale nie ma pustego elementu w Haskell (bardzo dużo według projektu), więc musisz użyć Monady Być może.

mylast :: [a] -> Maybe a 
mylast [] = Nothing 
mylast (x:[]) = Just x 
mylast (x:xs) = mylast xs 

Monady są nieco abstrakcyjnym tematem, ale potrzebujesz Monady, kiedy zaczynasz. Wszystko, co musisz wiedzieć o tym, to deklaracja typu, która mówi kompilatorowi, aby oczekiwał dwóch możliwości: "Nic" lub "Just x". Zwracający kod może następnie wziąć x i uruchomić z nim, ale jeśli zostawisz "Just", kompilator będzie narzekał.

Alternatywą jest wyrzucić błąd, gdy lista jest pusta napotkanych tak:

mynextlast [] = error "no empty lists allowed" 
mynextlast (x:[]) = x 
mynextlast (x:xs) = mynextlast xs 

Ale moje podejrzenie, że może to jest droga.

+6

Lekcja z tego jest taka, że ​​przydatne jest określenie typów definiowanych przez ciebie rzeczy. sprawi, że kompilacja będzie zawierała błędy, takie jak ta. – yairchu

+0

Dzięki za odpowiedzi wszystkim. Próbowałem ... mylast3 :: [a] -> Może mylast3 [] = Nothing mylast3 (x: []) = Tylko x mylast3 (x: xs) = mylast3 xs i uzyskać np. ... Main> mylast3 [2,4,66,5,4,33] Tylko 33 :: Może Integer Czy mimo to nie można drukować "just"? – user147056

+0

Dzięki za odpowiedzi wszystkim. Próbowałem ... mylast3 :: [a] -> Może mylast3 [] = Nothing mylast3 (x: []) = Tylko x mylast3 (x: xs) = mylast3 xs i dostaję np. ... Main> mylast3 [2,4,66,5,4,33] Tylko 33 :: Może Integer Czy mimo to nie można drukować "just"? – user147056

0

Dzięki za odpowiedzi wszystkim. Próbowałem ...

mylast :: [a] -> Maybe a 
mylast [] = Nothing 
mylast (x:[]) = Just x 
mylast (x:xs) = mylast xs 

i uzyskać np ...

Main> mylast3 [2,4,66,5,4,33] 
Just 33 :: Maybe Integer 

Czy mimo popełnienia nie to wydrukować 'tylko' w odpowiedzi?

[EDIT: Jörg W Mittag] (Komentarze są okropne dla opublikowania kodu ...)

Oto jak cały kod wygląda w kontekście:

mylast []  = Nothing 
mylast [x] = Just x 
mylast (x:xs) = mylast xs 

mylook (Just a) = do print a 
mylook Nothing = do error "Nothing to see here, move along!" 

mylook $ mylast [2,4,66,5,4,33] 
+2

Punkt Być może Monada (i to, co odróżnia go od, powiedzmy, wskaźników NULL w C lub zerowych odniesień w Javie), jest taki, że podpis typu wyraźnie zmusza cię do radzenia sobie w obu przypadkach: że coś zostało zwrócone i że nic nie zostało zwrócone . Tak więc, będziesz musiał jawnie dopasować wzór do obu przypadków i poradzić sobie z nimi osobno. Na przykład. jeśli chcesz wydrukować wynik: mylook (Just a) = drukuj a! NEWLINE! mylook Nic = błąd "Nic tu nie widać, ruszaj się!" !NOWA LINIA! mylook $ mylast [2,4,66,5,4,33] –

+0

'x <- mylast3 [2, 4, 66, 5, 4, 33]' – rampion

+0

co powiesz na "fromJust $ mylast [2,4,66, 5,4,33] "? (fromJust jest importowany z Data.Maybe) – newacct

0
myLast' [] = error "no empty lists allowed" 
myLast' [a] = a 
myLast' xs = xs !! (length xs - 1) 
+0

Dodaj więcej kontekstu do swojej odpowiedzi, aby wyjaśnić, co robi. – Adam

0
mylast [x] = x 
mylast (x:xs) = mylast xs 

rekurencyjne rozwiązania call