0

How can I write a function which receives a list, for example [7, 8, 9].

The function has inside an infinite list. It will calculate all divisors from an infinite list.

For example take 5 (f [7, 8, 9]) output will be [7, 8, 9, 14, 16]

Second example take 7 (f [7, 8, 9]) output will be [7, 8, 9, 14, 16, 18, 21]

I hope you can understand what I mean.

My code looks like this:

myFunction list = [x | x <- [1..], el <-[list], x `mod` el == 0]

My code works only with constant list. If I write

myFunction list = [x | x <- [1..], el <-[7, 8], x `mod` el == 0]

It works only for 7 and 8

How can I pass an arbitrary list?

icc97
  • 11,395
  • 8
  • 76
  • 90
Haskell
  • 115
  • 9
  • 5
    `[list]` is a single-element list (the one element being `list`). Did you mean `el <- list`? – melpomene Jan 13 '19 at 14:14
  • Your logic looks suspect to me. What's the expected result of `take 10 (myFunction [2, 3])`? – melpomene Jan 13 '19 at 14:15
  • @melpomene (take 10 (myFunction [2, 3]) output will be [2, 3, 4, 6, 8, 9, 10, 12, 14, 15] all first 10 numbers from infinity numbers which we can divide without remainder. yes it is multiplies – Haskell Jan 13 '19 at 14:20
  • Well, your function actually returns `[2,3,4,6,6,8,9,10,12,12]`. [Live demo](https://tio.run/##TYxLCoAgAAX3neItCyyytrntEiIoJSR@ijIo6O6Wu5Yzw3uLOqx2LiV/j2eYolkDnDkiGPiFBxeGGpw2jSDQLkOu5PPSr7PMjjG0oii8MuFbbbsJEWVUVoO2KH@/vCPoRVWl9AI). – melpomene Jan 13 '19 at 14:22
  • You are correct. this output is not correct. I want output without duplicate. How can filter this list from duplicate? – Haskell Jan 13 '19 at 14:27
  • 1
    Instead of binding `list` you could try ``any (\el -> x `mod` el == 0) list`` – luqui Jan 13 '19 at 15:07
  • 2
    Alternatively you could use `nub` from `Data.List` to remove duplicates but it's unnecessarily inefficient to do it that way – luqui Jan 13 '19 at 15:08
  • @luqui It works perfectly thanks. But I don't understand, how any function in this case works? – Haskell Jan 13 '19 at 15:19
  • 2
    may be duplicate: https://stackoverflow.com/questions/54107722/how-to-make-a-sorted-list-of-multiples-for-several-numbers – assembly.jc Jan 13 '19 at 15:35
  • 2
    Possible duplicate of [How to make a sorted list of multiples for several numbers?](https://stackoverflow.com/questions/54107722/how-to-make-a-sorted-list-of-multiples-for-several-numbers) – steve Jan 13 '19 at 15:59
  • See also [New state of the art in unlimited generation of Hamming sequence](https://stackoverflow.com/q/12480291/791604), which *starts* from the solution listed as an answer here and improves from there. – Daniel Wagner Jan 14 '19 at 16:09

1 Answers1

3

First let’s solve the case for a single item instead of a list:

multiples n | n > 0 = [n * i | i <- [1..]]

That was easy enough. Now suppose we have multiples 2 and multiples 3, how can we compute multiples [2,3], i.e. the increasing sequence of numbers made of the multiples of 2 or 3, or in other words, the increasing list of numbers made that are either in the increasing list of numbers multiples 2 or multiples 3? Try this:

merge (x:xs) (y:ys) = case compare x y of
  GT -> y : merge (x:xs) ys
  LT -> x : merge xs (y:ys)
  EQ -> x : merge xs ys

So now we can implement the desired function:

f (x:xs) = foldr merge (multiples x) (multiples <$> xs)
Dan Robertson
  • 4,315
  • 12
  • 17