2014-09-11 3 views
5

Voglio restituire tutti i cubi (x^3) che sono meno di un parametro Int utilizzando una comprensione di lista. Ho il seguente:Come rompere | pausa | ritorno in una comprensione di lista Haskell

cubesLessThanN :: Int -> [Int] 
cubesLessThanN int = [if x * x * x <= int then x else * | x <- [0..int]] 

L'asterisco è dove sto avendo il problema. Voglio interrompere l'elaborazione del loop una volta che si verifica else. L'ultimo [list] dovrebbe avere solo i cubi, non gli altri valori di x. Non mi interessa davvero come succede, ma vorrei sapere le opzioni e quali sono le differenze (se ce ne sono).

Se provo a restituire null, Nothing, '' e alcuni altri. So che dovrei restituire un tipo di int se restituisco qualcosa.

+0

non è possibile utilizzare la lista condizioni di comprensione? – Mephy

risposta

7

di lista supportano guardie.

[x | x <- [0..int], x^3 <= int] 

Dal list comprehension sono lo zucchero per la lista Monade, questo equivale a utilizzare la funzione guard in un do blocco:

do 
    x <- [0..int] 
    guard (x^3 <= int) 
    return x 

Se desugar questo in >>= e InLine le definizioni di >>= e guard:

concatMap (\x -> if x^3 <= int then [x] else []) [0..int] 

Questo è simile a un filt ER.

filter (\x -> x^3 <= int) [0..int] 

Controllo dello stato continuerà (pigramente) anche dopo il valore della x^3 supera il valore di int. Per evitare ciò, puoi usare takeWhile perché sai che la tua funzione è monotona.

takeWhile (\x -> x^3 <= int) [0..int] 
11

Uso takeWhile:

cubesLessThanN :: Int -> [Int] 
cubesLessThanN int = takeWhile ((<= int) . (^3)) [0..] 
+0

Questa è considerata una comprensione di lista? –

+4

@chrisFrisina: No, ma non puoi farlo solo con una lista di comprensione. Puoi far escludere gli elementi rimanenti, ma non è la stessa cosa (meno efficiente e non funziona su liste infinite). La cosa più vicina sarebbe probabilmente 'map fromJust $ takeWhile isJust $ [se x * x * x <= int then Solo x else Nothing | x <- [0 ..]] '. – Ryan

+2

Per aggiungere al commento di minitech, le comprensibilità delle liste vanno solo così lontano; quando inizi a fare cose più complesse, è meglio imparare a usare la più ampia varietà di cose offerte nel ['Data.List'] (http://hackage.haskell.org/package/base-4.7.0.1/docs/ Data-List.html) modulo libreria (come 'takeWhile'). –

1

Prendere una radice cubica

[ x^3 | x <- [ 1 .. ceiling (fromIntegral int ** (1/3)) ], x^3 < int ] 

Ad esempio:

λ let int = 1000 in [ x^3 | x <- [ 1 .. ceiling (fromIntegral int ** (1/3)) ], x^3 < int ] :: [Int] 
[1,8,27,64,125,216,343,512,729] 
+0

Questo risulta in '[0,1,8,27]' sia per '27' che' 64'. – Ryan

+0

minitech: grazie, risolto. – rampion

+0

Ora includerà 1000 per qualsiasi cosa in (729, 1000). – Ryan