Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have multiple infinite ranges in list comprehensions?

Tags:

haskell

In haskell I have a list comprehension like this:

sq = [(x,y,z) | x <- v, y <- v, z <- v, x*x + y*y == z*z, x < y, y < z]
    where v = [1..]

However when I try take 10 sq, it just freezes... Is there a way to handle multiple infinite ranges?

Thanks

like image 415
omega Avatar asked Mar 19 '13 21:03

omega


People also ask

Can we write two for loops in list comprehension?

Example 7: Transpose of Matrix using Nested Loops The above code use two for loops to find transpose of the matrix. We can also perform nested iteration inside a list comprehension. In this section, we will find transpose of a matrix using nested loop inside list comprehension.

Are list comprehensions more efficient than for loops?

As we can see, the for loop is slower than the list comprehension (9.9 seconds vs. 8.2 seconds). List comprehensions are faster than for loops to create lists. But, this is because we are creating a list by appending new elements to it at each iteration.

How do you use two loops in a list comprehension in Python?

Simple do Outermost loop comes first, and then the inner loops subsequently to get List comprehension double for loop in Python.

How do you do a double list comprehension?

Use a list comprehension to do a double iteration. Use the syntax [value for object in iterable for value in object] to iterate through iterable in the outer loop, iterate through object in the inner loop, and extract every value from each object in iterable . text = [["Hello", "World!"], ["Lets", "Eat!"]]


1 Answers

In addition to the other answers explaining the problem, here is an alternative solution, generalized to work with level-monad and stream-monad that lend themselves for searches over infinite search spaces (It is also compatible with the list monad and logict, but those won't play nicely with infinite search spaces, as you already found out):

{-# LANGUAGE MonadComprehensions #-}

module Triples where

import Control.Monad

sq :: MonadPlus m => m (Int, Int, Int)
sq = [(x, y, z) | x <- v, y <- v, z <- v, x*x + y*y == z*z, x < y, y < z]
    where v = return 0 `mplus` v >>= (return . (1+))

Now, for a fast breadth first search:

*Triples> :m +Control.Monad.Stream
*Triples Control.Monad.Stream> take 10 $ runStream sq
[(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17),(12,16,20),(7,24,25),
(15,20,25),(10,24,26),(20,21,29)]

Alternatively:

*Triples> :m +Control.Monad.Levels
*Triples Control.Monad.Levels> take 5 $ bfs sq   -- larger memory requirements
[(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17)]
*Triples Control.Monad.Levels> take 5 $ idfs sq  -- constant space, slower, lazy
[(3,4,5),(5,12,13),(6,8,10),(7,24,25),(8,15,17)]
like image 177
danlei Avatar answered Sep 22 '22 00:09

danlei