2011-05-20 24 views
10

¿Hay alguna manera de usar let, where o definir de otra manera las subexpresiones en una lista de comprensión para que pueda usarse tanto en el término como en la restricción?haskell - let/where equivalente dentro de la lista de comprensión?

Desde mi experimentación, los siguientes trabajos:

[let x = i*i in x | i<-[1..10], i*i > 20] --good 
[i*i | i<-[1..10], let x=i*i in x > 20]  --good 

Pero estos no hacen BC de alcance:

[let x = i*i in x | i<-[1..10], x > 20] -- 'x' not in scope error 
let x = i*i in [x | i<-[1..10], x > 20] -- 'i' not in scope error 
[x | i<-[1..10], x > 20] where x = i*i --parse error on 'where' 

Así let obras en un lugar u otro, pero no ambos a la vez!

La única forma que he encontrado para hacerlo funcionar (es decir, evitar las repetidas expresiones y posiblemente evaluaciones) es añadir un conjunto unitario lista tonta como lo hice en el siguiente problema (Euler project 38) con x<-[e38cat i [1..k] como constraitnt a la comprensión de lista:

> let e38cat x l = foldl1 (++) $ map show [x*i | i<-l] 
maximum [x| i<-[1..9999], k<-[2..div 10 $ length $ show i], x<-[e38cat i [1..k]], sort x == "123456789"] 
"932718654" 

O contunuing el ejemplo trivial anterior,

[x | i<-[0..10], x<-[i*i], x > 20] --works 

Esto parece un poco tonto, y se le faltaba algo de claridad, aunque no parece demasiado ineficiente. Aún así, sería bueno si let o where funcionaran en toda la comprensión. Se puede hacer esto?

+1

Su segundo ejemplo, '[x | i <- [1..10], deje x = i * i en x> 20] ', no compila; ¿quisiste decir '[i * i | i <- [1..10], deje x = i * i en x> 20] '? –

+0

sí, gracias. si el primero funcionó, habría respondido mi propia pregunta –

Respuesta

19

lo escribe así:

[x | i <- [0..10], let x = i*i, x > 20] 

Aviso no hay in. Puede consultar x tanto en el término como en cualquier restricción posterior al let. Esta forma de let corresponde a la una en do -notation:

do i <- [0..10] 
    let x = i*i 
    guard (x > 20) 
    return x 

Aquí x está en el ámbito de la let hasta el final de la do -bloque.

+0

gracias, sabía que tenía que haber algo. Me hubiera sentido realmente decepcionado si esto fuera solo un gran vacío en el lenguaje = P –

+1

@jon_darkstar, oh, no te dejes engañar. Hay numerosos agujeros en el lenguaje. Por ejemplo, el que 'Applicative' debe llenar. – luqui

5

Casi lo tenía; simplemente escriba [x | i <- [0..10], let x = i*i, x > 20] (observe , en lugar de in). Es muy similar al do -notación (de hecho, puede usar do -notación en su lugar, y una extensión GHC reciente le permite usar listas de comprensión para mónadas arbitrarias). Si tienes curiosidad, se puede encontrar la sintaxis in the Haskell 98 report:

aexp -> [ exp | qual_1 , ... , qual_n ] (list comprehension, n >= 1) 
qual -> pat <- exp      (generator) 
    | let decls      (local declaration) 
    | exp        (guard) 

Como se puede ver, uno de los calificadores válidos es let decls, que es exactamente lo que quería.

Cuestiones relacionadas