2012-01-04 8 views
6

Se ho due stringhe utilizzare un elenco di comprensione per ottenere il risultato desiderato:Haskell di lista in numero variabile di corde

combineStrings firstStr sndStr = [ [a,b] | a <- firstStr, b <- sndStr] 

Per tre corde, io uso questo

combineStrings firstStr sndStr trdStr = [ [a,b,c] | a <- firstStr, b <- sndStr, c <- trdStr] 

Quello che ho sto cercando di ottenere lo stesso risultato per un numero variabile di stringhe. Per esempio, se ho una funzione che prende la seguente forma:

combineStrings :: [String] -> [String] 

sto cercando di ottenere gli stessi risultati di cui sopra per 2, 3 ... n liste ... Ho provato diversi modi, come questo uno

combineStrings []  = [] 
combineStrings (hd:tl) = [ a:b | a <- hd, b <- combineStrings tl] 

ma questo non riesce a causa di [] sulla prima clausola. Qualcuno può aiutarmi a scrivere questo, per favore?

+3

Come regola generale, è possibile provare a rendere i tipi il più generici possibile. Qui il tuo codice non è specifico per le stringhe e può essere utilizzato per tutte le liste, quindi puoi scrivere 'combineStrings :: [[a]] -> [[a]]'. Quindi, la prima riga della risposta di undur_gongor può essere scritta 'combineStrings [] = [[]]'. Puoi anche provare a scrivere 'combineStrings' usando' foldr', dato che si adatta al modello di piega. – sdcvvc

risposta

9

Prova

combineStrings [] = [""] 

o meglio (come sottolineato da sdcwc):

combineStrings [] = [[]] 

In caso contrario, la parte b <- combineStrings tl della lista di comprensione non si produrrà alcun b e sarai sempre finire con un matrice vuota.

Ha senso anche come caso limite: l'unico modo per combinare caratteri da zero stringhe è una stringa vuota (costituita da zero caratteri).

+0

Aw man, non posso crederci. Grazie :) – Adi

15

Notevoli Haskell ha già tale funzione, appena un po 'più generale:

Prelude> :t sequence 
sequence :: Monad m => [m a] -> m [a] 
Prelude> sequence ["ab","cd","12"] 
["ac1","ac2","ad1","ad2","bc1","bc2","bd1","bd2"] 

[] è un'istanza di Monad, quindi in questo caso la firma diventa sequence :: [[a]] -> [[a]], con a = Char, sequence :: [String] -> [String].

+0

Mi chiedo quante funzioni come questa sono riscritte dai nuovi arrivati ​​come me .. Ma è un'esperienza di apprendimento :) Grazie – Adi

+4

Molte. Ed è una buona cosa, a patto che venga loro detto abbastanza presto che esiste già una funzione (più generale, di solito) nelle librerie standard, perché, come hai detto, è una buona esperienza di apprendimento. Solo, una volta capito come funziona scrivendo la tua versione, usa la funzione di libreria che altri Haskeller già conoscono. –

+1

Hoogle e HLint sono lì per aiutarti. – nponeccop

Problemi correlati