2009-07-29 14 views
7

Sto cercando di insegnarmi Haskell. Una cosa che ho cercato di fare è scrivere una funzione alternativa per restituire l'ultimo elemento di una lista ricorrendo alla lista finché la coda è il set vuoto e quindi restituendo la testa. Ho ...Implementazione dell'ultima funzione

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

... ma ho un errore quando provo ogni lista non vuota :( eventuali suggerimenti riguardo a quello che ho fatto di male? TIA.

+1

Dovreste accettare risposta rtperson ... – yeyeyerman

risposta

8

Prova mylast [] = error "Empty list!" . in caso contrario, invece Haskell non può dedurre il tipo di funzione

6

soluzione di Efraim dovrebbe funzionare (up-votato) ma penso che questo è un po 'più "Haskell-like":..

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

Disclaimer: Non l'ho ancora provato. Potrei aver commesso errori di sintassi.

+2

La carrure è la stessa [ x], giusto? IOW, l'unico elenco di elementi creato concatenando x con la lista vuota "(x: [])" è lo stesso dell'elenco contenente solo x "[x]". Non so quale sia più idiomatico, comunque. –

+0

No, Solo x non è uguale a [x]. –

+0

Oh, aspetta, capisco cosa intendi. Sì, il caso intermedio è la lista che contiene solo una x. Ma tutte le liste possono essere espresse come una testa e una coda, anche se una o entrambe sono vuote. –

29

Il problema - come tanti altri quando stai imparando Haskell - è quello della digitazione. Digitare quanto segue in GHCi

:t mylast 

e vedrete che la firma tipo è

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

che si aspetta una lista di liste e restituirà un elenco. Quindi se inserisci un elenco di stringhe ["bob", "fence", "house"] la funzione funzionerà come hai scritto tu.

Il problema è il caso base: mylast [] = [], che indica al compilatore che si desidera restituire un elenco. Vuoi restituire un elemento, non una lista. Ma non c'è alcun elemento vuoto in Haskell (molto di design), quindi è necessario usare la Forse monade.

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

Le Monade sono un argomento un po 'astratto, ma hai bisogno della monade Forse quando inizi. Tutto quello che devi sapere è che è una dichiarazione di tipo che dice al compilatore di aspettarsi due possibilità: "Niente" o "Solo x". Il codice restituito può quindi prendere x e correre con esso, ma se si omette "Just", il compilatore si lamenterà.

L'alternativa è quella di lanciare un errore quando si incontra un elenco vuoto, in questo modo:

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

Ma il mio sospetto è che forse è la strada da percorrere.

+6

una lezione da questo è che è utile specificare i tipi di cose che si definiscono. farà in modo che la compilazione catturi bug come questo .. – yairchu

+0

Grazie per le risposte a tutti. Ho provato ... mylast3 :: [a] -> Forse un mylast3 [] = Nothing mylast3 (x: []) = x Proprio mylast3 (x: xs =) mylast3 xs e ottengo es. ... Principale> mylast3 [2,4,66,5,4,33] Solo 33 :: Forse intero Esiste comunque la possibilità di non stampare il "giusto"? – user147056

+0

Grazie per le risposte a tutti. Ho provato ... mylast3 :: [a] -> Forse un mylast3 [] = Nothing mylast3 (x: []) = x Proprio mylast3 (x: XS) = mylast3 xs e ottengo ad esempio ... principale> mylast3 [2,4,66,5,4,33] soli 33 :: Forse Integer c'è comunque di rendere non stampare il 'solo'? – user147056

0

Grazie per le risposte a tutti. Ho provato ...

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

e ottengo pe ...

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

C'è comunque di rendere non stampare il 'solo' nella risposta?

[EDIT: Jörg W Mittag] (I commenti sono orribili per la pubblicazione del codice ...)

Ecco come l'intero codice appare nel contesto:

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

Il punto di Maybe Monad (e ciò che lo distingue, per esempio, da puntatori NULL in C o riferimenti null in Java), è che la firma del tipo obbliga esplicitamente ad affrontare entrambi i casi: che qualcosa è stato restituito e che non è stato restituito nulla . Quindi, dovrai concordare esplicitamente la corrispondenza su entrambi i casi e gestirli separatamente. Per esempio. se vuoi stampare il risultato: mylook (Just a) = stampa un! NEWLINE! mylook Nothing = errore "Niente da vedere qui, muoviti!" !NUOVA LINEA! mylook $ mylast [2,4,66,5,4,33] –

+0

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

+0

che dire di "fromJust $ mylast [2,4,66, 5,4,33] "? (fromJust viene importato da Data.Maybe) – newacct

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

Aggiungi più contesto alla tua risposta per spiegare cosa sta facendo. – Adam

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

soluzione chiamata ricorsiva

Problemi correlati