[Haskell-beginners] Haskell triangular loop (correct use of (++))

rohan sumant r.s.sumant at gmail.com
Mon Apr 11 02:05:08 UTC 2016


@Silent Leaf

I am indeed familiar with the list comprehension syntax indeed. I agree
with you that it certainly is the better alternative to writing handcrafted
functions especially when they involve (++). However the code you have
mentioned doesn't get the job done correctly. Your approach implements a
square nested loop which makes it at least twice as inefficient than the
one I am rooting for. The problem lies with the dropWhile function. It will
begin from the start of the list for every new (x,ix). This is particularly
bad in Haskell because the garbage collector cannot do away with
unnecessary prefixes of the input string, thereby wasting a lot of memory.




Rohan Sumant


On Sun, Apr 10, 2016 at 11:42 PM, Silent Leaf <silent.leaf0 at gmail.com>
wrote:

> Dunno if that's what you're interested in, or if it's best in terms of
> efficiency, but there's syntax inside the language made just for this kind
> of thing, called list comprehension. It comes from math's definition of
> sets by comprehension, and since it's part of the language I'd have a
> tendency to trust its efficiency, but I might be entirely wrong on this
> aspect.
>
> Anyways, for your problem, say I want to create the set of pairs of your
> example:
>
> let result = [(x,y) | let xs = [1,2,3,0], (x,ix) <- zip xs [1,2..], y <-
> drop ix xs, x /= y]
> in result == [(1,2),(1,3),(1,0),(2,3),(2,0),(3,0)]
>
> Basically the syntax is: [ parameterized result element | conditions on
> the parameters]
> the conditions being a sequence of comma-separated items that are either:
> local variable declarations without the 'in', example being (let input =
> [1,2,3,0]), pattern-accepting generation of values from a list, or
> conditions on the parameters (here x and y).
>
> In order to build y's list I decided to zip xs with a list of indexes
> starting to 1, thereby ensuring no pair is twice in, considering the order
> doesn't matter.
> I'd bet the syntax is monad/do related, with all those right-to left
> arrows. Plus it fits the bill of what's actually happening here.
>
> Of course if you want a function, you can still write thereafter
> mkpairs :: Integral a => a -> [(a,a)]
> mkpairs n = [(x,y) | let xs = [1..n] ++ [0], (x,ix) <- zip xs [1,2..], y
> <- drop ix xs, x /= y]
>
> If you don't care about the order, I guess xs = [0..n] will be much more
> efficient, relatively speaking.
> Pretty sure the function even works for n == 0, since y <- drop 1 [0]
> won't have a thing to yield, hence, result = [].
>
> If that interests you:
> https://wiki.haskell.org/List_comprehension
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20160411/88f511d1/attachment.html>


More information about the Beginners mailing list