9

I wrote the following function in haskell, as it will enumerate every integer:

integers = (0:)$ concat $ zipWith (\x y -> [x,y]) [1..] (map negate [1..])

I wonder if there are better ways to do it, it does seem a bit too complicated.

Also, I wonder are there standard implementations to list all elements in the integer lattice of dimension $k$.

deceze
  • 510,633
  • 85
  • 743
  • 889
Chao Xu
  • 2,156
  • 2
  • 22
  • 31

6 Answers6

19
integers = 0 : concat [[x,(-x)] | x <- [1..]]

(or, alternatively, as in @DanielWagner's solution in the comment below that works better I think)

Riccardo T.
  • 8,907
  • 5
  • 38
  • 78
6
import Control.Applicative

integers = 0 : zipWith (*) ([1..] <* "mu") (cycle [1,-1])

Of course you can take the path of the non-monk as well:

integers = 0 : [y | x <- [1..], y <- [x,-x]]

But then you won't understand the true meaning of mu.

Landei
  • 54,104
  • 13
  • 100
  • 195
3
map fun [0 .. ]
  where
    fun n
      | even n = n `quot` 2
      | otherwise = (1 - n) `quot` 2

There aren't any standard implementations to list all points in ℤk. Not even for k == 1, really. But with any enumeration of ℤ and a cartesian product of two lists that outputs any pair at a finite index even if the lists are infinite (some possible implementations here), you can roll your own.

integers :: [Integer]
integers = -- whatever is your favourite implementation

-- get all pairs at finite index, even for infinite input lists
-- 
cartesian :: [a] -> [b] -> [(a,b)]
cartesian xs ys = ???

-- enumDim k enumerates the points in ℤ^k, to avoid type problems, the points
-- are represented as lists of coordinates, not tuples
enumDim :: Int -> [[Integer]]
enumDim k
  | k < 0     = error "Can't handle negative dimensions"
  | k == 0    = [[]]
  | otherwise = map (uncurry (:)) $ cartesian integers (enumDim (k-1))
  -- alternative:
  {-
  | k == 1    = map return integers
  | otherwise = map (uncurry (++)) $ cartesian (enumDim h) (enumDim (k-h))
    where
      h = k `quot` 2
  -}
Community
  • 1
  • 1
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
2

map (*) [1..] <*> [1,-1] which can be rewritten

(*) <$> [1..] <*> [1,-1]` 

or even

liftA2 (*) [1..] [-1,1]
mb14
  • 22,276
  • 7
  • 60
  • 102
  • and for "the integer lattice of dimension $k$"? can something be done in this vein there? – Will Ness Mar 05 '18 at 10:32
  • like Q (k=2) ? I don't think it will work with applicative, but it should work with monad or list comprension. It that case you can do things like [(p,q) | p <- [1..], q <- [-p..p] ]. (It's probably incorrect but you got the idea) ... – mb14 Mar 05 '18 at 12:34
1

We have had many short solutions. Here is a systematic one, with tuples of integers as well.

-- interleave lists
interleave :: [a] -> [a] -> [a]
interleave [] ys = ys
interleave xs [] = xs
interleave (x:xs) (y:ys) = x : y : interleave xs ys

-- positive integers
positiveIntegers = 1 : [k + 1 | k <- positiveIntegers]

-- negative integers
negativeIntegers = map negate positiveIntegers

-- integers
integers = 0 : interleave positiveIntegers negativeIntegers

-- enumeration of the cartesian product of two lists
prod :: [a] -> [b] -> [(a,b)]
prod [] ys = []
prod xs [] = []
prod (x:xs) (y:ys) = (x,y) : interleave (interleave xys yxs) (prod xs ys)
    where xys = map (\y -> (x,y)) ys
          yxs = map (\x -> (x,y)) xs

-- the k-fold power of a list
power :: Int -> [a] -> [[a]]
power 0 xs = [[]]
power k xs = map (\(y,ys) -> y:ys) (prod xs (power (k-1) xs))

-- all quadruples of integers
integerQuadruples = power 4 integers

-- the millionth quadruple is [62501,0,0,1]
something = integerQuadruples !! 1000000
Andrej Bauer
  • 2,458
  • 17
  • 26
0
[0..] ++ [ -x | x <- [1..] ]

A much simpler method than some which were posted here (although it's not the usual order).

jwg
  • 5,547
  • 3
  • 43
  • 57