[Haskell-beginners] List comprehensions with multiple generators

Ut Primum utprimum at gmail.com
Sun Apr 26 13:35:55 UTC 2020

I'll try to explain the meaning of different parts of the comprehension::

unique xs = [x | *(x,y) <- zip xs [0..]*, x `notElem` (take y xs)]
*this* part means: consider the couples (x,y) that are output of zip xs
for example if xs = [10,20,10,30,30], you are taking

unique xs = [x | (x,y) <- zip xs [0..], *x `notElem` (take y xs)*]
*this* part means: among the things you considered before (i.e. all the
couples obtained before), consider only those that satisfy the property
that the first element of (x,y) is not an alement of a certain list (take y
xs, i.e. the first y elements of xs).
So in the example above:
      is 10 an element of (take 0 xs)=[ ] ? No ----> we consider (10,0)
      is 20 an element of (take 1 xs)=[10]? No ----> we consider (20,1)
      is 10 an element of (take 2 xs)=[10,20]? Yes ----> we DON'T consider
      is 30 an element of (take 3 xs)=[10,20,10]? No ----> we consider
      is 30 an element of (take 4 xs)=[10,20,10,30]? Yes ----> we DON'T
consider (30,4)
So we are considering only [(10,0),(20,1),(30,3)]
So as you said this is a refinement of the elements generated by the first
generator. A refinement means that some of the elements generated before
are (possibly) discarded, so you don't obtain a [Bool], but something of
the same type of what was generated before, i.e. another [(Eq,Int)]
possibly shorter than the previous one.

unique xs =* [x |* (x,y) <- zip xs [0..], x `notElem` (take y xs)]
*this* part says that, of each couple produced and refined before, you take
the first element (that was called x).
So in the example you get [10,20,30]

Hope this is clear,

Il giorno dom 26 apr 2020 alle ore 14:51 Ken Overton <ken.overton at gmail.com>
ha scritto:

> Hello all,
> I recently came across this function which made me realize I don't
> understand list comprehensions well. I hope someone can help me understand
> them better by understanding this example better. The function takes a list
> of Eq and returns the list of unique elements from it:
>     unique :: Eq a => [a] -> [a]
>     unique xs = [x | (x,y) <- zip xs [0..], x `notElem` (take y xs)]
> It's using a list comprehension with multiple 'generators' (hope I have
> the term correctly). My understanding of multiple generators in a list
> comprehension is that they refine the results of the previous generator.
> So the first generator should produce [(Eq,Int)] as input to the second
> generator? And the second generator should produce [Bool]?
> My understanding must be wrong though; how do we end up with just the
> items where the second generator produced True?
> Thanks,
> --
> Ken Overton
> (917) 863-3937
> ken.overton at gmail.com
> _______________________________________________
> 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/20200426/1a7deb9d/attachment.html>

More information about the Beginners mailing list