2012-01-04 12 views
6

Si tengo dos cuerdas que utilizar una lista por comprensión para obtener el resultado deseado:lista Haskell comprensión de número variable de cuerdas

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

Durante tres cuerdas, que usan este

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

Lo que Lo que intento es obtener el mismo resultado para un número variable de cadenas. Por ejemplo, si tengo una función que toma la forma siguiente:

combineStrings :: [String] -> [String] 

Estoy tratando de obtener los mismos resultados que el anterior para 2, 3 ... n listas ... He intentado varias formas, como este uno

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

pero esto falla debido a [] en la primera cláusula. ¿Alguien puede ayudarme a escribir esto, por favor?

+3

Como regla general, puede tratar de hacer tipos lo más generales posible. Aquí su código no es específico para cadenas, y se puede usar para todas las listas, por lo que puede escribir 'combineStrings :: [[a]] -> [[a]]'. Entonces, la primera línea de la respuesta de undur_gongor puede escribirse 'combineStrings [] = [[]]'. También puede intentar escribir 'combineStrings' utilizando' foldr', ya que se ajusta al patrón de plegado. – sdcvvc

Respuesta

9

Trate

combineStrings [] = [""] 

o mejor (como ha señalado sdcwc):

combineStrings [] = [[]] 

De lo contrario la parte b <- combineStrings tl de la lista por comprensión, no dieron b y siempre se va a terminar con una matriz vacía

También tiene sentido como caso de borde: la única manera de combinar caracteres de cero cadenas es una cadena vacía (que consta de cero caracteres).

+0

Aw hombre, no puedo creerlo. Gracias :) – Adi

15

Notable: Haskell ya tiene esa función, sólo un poco más general:

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

[] es una instancia de Monad, por lo que en este caso la firma se convierte en sequence :: [[a]] -> [[a]], con a = Char, sequence :: [String] -> [String].

+0

Me pregunto cuántas funciones como esta son reescritas por los recién llegados como yo ... Pero es una experiencia de aprendizaje :) Gracias – Adi

+4

Muchos. Y es algo bueno, siempre y cuando se les diga lo suficientemente pronto que hay una función (más general, por lo general) en las bibliotecas estándar, porque, como dijiste, es una experiencia de aprendizaje "muy buena". Simplemente, una vez que hayas descubierto cómo funciona escribiendo tu propia versión, utiliza la función de biblioteca que otros Haskellers ya conocen. –

+1

Hoogle y HLint están para ayudarlo. – nponeccop

Cuestiones relacionadas