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