2013-04-27 17 views
5

Ho insegnato a me stesso Haskell per circa un mese e oggi stavo leggendo la soluzione del sedicesimo problema e mi è venuta una domanda.Eliminare l'elemento dalla lista

Questo è il link: http://www.haskell.org/haskellwiki/99_questions/Solutions/16

In sostanza, questa domanda chiede di fare una funzione che scende ogni elemento N'th da un elenco. Per esempio,

*Main> dropEvery "abcdefghik" 3

"abdeghk"

La prima soluzione nel link è

dropEvery :: [a] -> Int -> [a] 
dropEvery [] _ = [] 
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

mia domanda è perché dropEvery definisce il caso di liste vuote mentre dropEvery' può prendersi cura di lista vuota? Penso che dropEvery [] _ = [] possa essere semplicemente eliminato e modificando un po 'di altre frasi come segue dovrebbe funzionare esattamente come sopra e sembra più breve.

Qualcuno può aiutarmi a capire questo?

+1

Si noti che l'ordine degli argomenti di questa funzione è "sbagliato"; funzioni come questa sono solitamente 'Int -> [a] -> [a]', che è normalmente molto più utile per le situazioni di pipeline. Perché l'hanno messo al contrario in quell'esempio, non ne ho idea. – leftaroundabout

risposta

7

Penso che siano uguali e l'autore avrebbe potuto semplificare il codice come suggerito. Per quanto mi riguarda ho provato entrambe le versioni con QuickCheck e sembrano essere uguali.


import Test.QuickCheck 

dropEvery :: [a] -> Int -> [a] 
dropEvery [] _ = [] 
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

dropEvery2 :: [a] -> Int -> [a] 
dropEvery2 xs n = dropEvery' xs n 1 
    where 
     dropEvery' (x:xs) n i = (if (n `divides` i) then [] else [x])++ (dropEvery' xs n (i+1)) 
     dropEvery' [] _ _ = [] 
     divides x y = y `mod` x == 0 

theyAreSame xs n = (dropEvery xs n) == (dropEvery2 xs n) 
propTheyAreSame xs n = n > 0 ==> theyAreSame xs n 

E in ghci si può fare

*Main> quickCheck propTheyAreSame 
+++ OK, passed 100 tests. 

Ho anche provato un paio di casi d'angolo a mano

*Main> dropEvery [] 0 
[] 
*Main> dropEvery2 [] 0 
[] 
*Main> dropEvery [] undefined 
[] 
*Main> dropEvery2 [] undefined 
[] 

Così li sembrano la stessa.

Così i nostri risultati di apprendimento:

  1. QuickCheck è perfetto per questo genere di cose
  2. Non sottovalutare te stesso. :)
+0

Grazie per la risposta! Sono felice di sapere che la mia ipotesi era corretta. Non sapevo di Quickcheck. Devo essere in grado di usare GHC per usarlo? – Tengu

+0

@Tengu Non usi GHC? Puoi anche usare 'runghc' o' ghci', ma sono sicuro che QuickCheck funzionerà anche su compilatori completamente diversi. Puoi google per una guida all'installazione ma poiché è una libreria molto comune dovrebbe essere molto facile da installare. – Tarrasch

+0

Ho appena iniziato Haskell il mese scorso e non ho mai usato il compilatore GHC. (Beh, in realtà non so nemmeno cosa significhi "compilatore" al primo posto, anche se il mio amico in informatica ha spiegato per me molte volte haha) cercherò il QuickCheck, ma potrei non essere preparato per queste cose. La ringrazio per la risposta! – Tengu

Problemi correlati