I want to return all the cubes (x^3) that are less than a parameter Int using a list comprehension. I have the following:
cubesLessThanN :: Int -> [Int]
cubesLessThanN int = [if x * x * x <= int then x else * | x <- [0..int]]
The asterisk is where I am having the problem. I kinda want to stop processing the loop once the else
happens. The final [list]
should only have the cubes, not the other values of x
. I don't care really how it happens, but would like to know the options, and what the differences are (if any).
If I try to return null
, Nothing
, ''
, and a few other ones. I know I am supposed to return a type of int
if I return anything at all.
Use takeWhile
:
cubesLessThanN :: Int -> [Int]
cubesLessThanN int = takeWhile ((<= int) . (^3)) [0..]
List comprehensions support guards.
[x | x <- [0..int], x ^ 3 <= int]
Since list comprehensions are sugar for the list monad, this is equivalent to using the guard
function in a do
block:
do
x <- [0..int]
guard (x ^ 3 <= int)
return x
If we desugar this into >>=
and inline the definitions of >>=
and guard
:
concatMap (\x -> if x ^ 3 <= int then [x] else []) [0..int]
This is akin to a filter.
filter (\x -> x ^ 3 <= int) [0..int]
Checking the condition will continue (lazily) even after the value of x ^ 3
exceeds the value of int
. To prevent that, you can use takeWhile
because you know that your function is monotonic.
takeWhile (\x -> x ^ 3 <= int) [0..int]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With