Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are some better ways to write [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] in Haskell?

I've run in to a few situations where I need the list:

[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] -- no (0,0)

Note that there is no (0,0) in the list. I use the (dx,dy) tuples to search up, down, left, right and diagonally from a coordinate.

Every time I write it I feel like there should be a more concise, and/or easier to read way to define it. I'm relatively new to Haskell and I figure somewhere in the bag of Applicative/Functor/Monad tricks there should be a neat way to do this.

I've tried:

[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]

Sometimes it's better just to write it out, but I don't think this is one of those times. It's not obvious with a glance that (0,0) isn't included, and you have to read it a bit to notice the pattern.

map (\[a,b] -> (a,b)) $ delete [0,0] $ sequence $ replicate 2 [-1,0,1]

I like the one above because I get to put the "2" in there which is a nice explicit way to say "We're doing the same sort of thing twice", but I can't accept the map in front with the big unsafe lambda and 2 names.

[(dx,dy) | let a = [-1,0,1], dx <- a, dy <- a, (dx,dy) /= (0, 0)]

This one has too many names in it, but uses the list comprehension exactly as it is designed. It might be easier to read for somebody who really likes list comprehensions, but I don't like all the names.

let x = [-1,0,1] in delete (0,0) $ (,) <$> x <*> x

That one looks prettier imo, but I don't have that "2" in there, and I have a name. This is my favorite so far, but it doesn't feel perfect.

I think if I understood how to write this better I might have a deeper understanding of Functors/Monads or the like. I've read about them quite a bit, and I've heard a bunch of words like fmap/mconcat/etc, but I don't know which one to grab for in this situation.

like image 990
Jake Brownson Avatar asked Jan 23 '14 23:01

Jake Brownson


People also ask

How many different ways to write a number?

Different Ways to Write a Number - Concept - Practice questions with answers. DIFFERENT WAYS TO WRITE A NUMBER. Three different ways to write a number are ... Sum of all three four digit numbers formed with non zero digits. Sum of all three four digit numbers formed using 0, 1, 2, 3.

What are the Best Writing Tips for beginners?

This is a straightforward writing tip for beginners, but a lot of people forget it. For example, your voice and elements of style for personal blogging will be much more informal than business writing (i.e writing a proposal for a new client). Being mindful of your audience is key to improving writing skills and creating more impactful work. 5.

How do I get better at business writing?

2. Embrace the writing “brain dump” In business writing, the “brain dump” signals the beginning of every new project or assignment. It’s the opportunity to get whatever is in your head out on digital paper in a stream of consciousness.

What makes a good writer?

Getting tone right is key to being a good writer. It’s the personality of your writing, influenced by the type of writing you’re doing and who you’re talking to. Just like we said in “Know Your Audience,” business writing like an email might sound conservative, while a personal social media post can be friendly and casual.


3 Answers

Actually, I think it's indeed best to write it out explicitly in this case. Just align it reasonably, and no questions stay open whatsoever:

neighbours = [ (-1,-1), (-1,0), (-1,1)
             , ( 0,-1),         ( 0,1)
             , ( 1,-1), ( 1,0), ( 1,1) ]

There's no way any alternative could be more self-explanatory than this.

Of course, there are more concise alternatives. Being a physics guy, I'd tend to

   [ (round $ - sin φ, round $ - cos φ) | φ <- [pi/4, pi/2 .. 2*pi] ]

which is of course more expensive to compute, but that doesn't matter if you only define this list at one place and re-use it from all over you program. The order is different here, not sure if that matters.

like image 173
leftaroundabout Avatar answered Sep 28 '22 08:09

leftaroundabout


Why not just use a list comprehension? They can have boolean guards in them, so excluding (0,0) is pretty simple:

[(i,j) | i <- [-1..1], j <- [-1..1], (i,j) /= (0,0)]

Note that as a Haskell newb myself, there is likely a more compact/efficient way to write that guard expression. Nonetheless, this gets the job done.

like image 31
Ben Avatar answered Sep 28 '22 06:09

Ben


Prelude Data.Ix Data.List> delete (0,0) (range ((-1,-1),(1,1)))
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
like image 41
Daniel Wagner Avatar answered Sep 28 '22 06:09

Daniel Wagner