# Working with groups of co-occuring events

**URL:** <https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098>\
**Category:** TidalCycles\
**Tags:** innards\
**Created:** [21 May 2020 19:04 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098 "2020-05-21T19:04:27Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [21 May 2020 19:04 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/1 "2020-05-21T19:04:27Z")

</div>

That is exactly what I was looking for, thank you!

@yaxu let's assume for a second there is no inversion in Tidal: how would then be possible to make @loopology's function work?

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [21 May 2020 20:59 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/2 "2020-05-21T20:59:09Z")

</div>

Moved to Innards as it's a bit involved..

I'd generalise the type so it works with any number, as in Tidal notes aren't integers but floats.

```haskell
inversion :: Num a => Int -> [a] -> [a]
inversion _ [] = []
inversion n xs = drop n xs ++ [x + 12 | x <- take n xs]

```

Then I'd get it to with with lists of Tidal events rather than values:

```haskell
eventInversion :: Num a => Int -> [Event a] -> [Event a]
eventInversion _ [] = []
eventInversion n xs = drop n xs ++ (fmap (fmap (+12)) $ take n xs )

```

I used fmap to work in the values inside events, and for brevity used fmap on the list too instead of the list comprehension.

Then I made this function that allows you to group any co-occuring events and work on them together:

```haskell
withFriends :: ([Event a] -> [Event b]) -> Pattern a -> Pattern b
withFriends f pat = withEvents munge pat
  where munge es = concatMap (f) (groupBy (\a b -> whole a == whole b) $ sortOn whole es)

```

Then bring it together:

```haskell
invert :: Num b => Int -> Pattern b -> Pattern b
invert = withFriends . eventInversion

```

```haskell
d1 $ n (invert 2 "c'maj e'min'4") $ sound "superpiano"

```

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [21 May 2020 21:13 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/3 "2020-05-21T21:13:00Z")

</div>

It's complicated because tidal patterns are functions from time to events, so you have to make a function that intercepts values on the way out of the pattern, grouping together ones happening at the same time.

Here's a less attractive version of `inversion` that works with negative inversions:

```haskell
inversion :: Num a => Int -> [Event a] -> [Event a]
inversion _ [] = []
inversion n xs = map (\i -> fmap (+ (fromIntegral $ (i `div` l)*12)) (xs !! (i `mod` l))) $ take l [n ..]
  where l = length xs

```

---

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [21 May 2020 22:05 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/4 "2020-05-21T22:05:55Z")

</div>

Thanks for the explanation @yaxu, there are quite many things that I am not able to understand.  
I will try to summarise them, feel free to skip if you think we are going down the rabbit hole and perhaps it is better to wait.

> [@yaxu](#):
>
> I used fmap to work in the values inside events, and for brevity used fmap on the list too instead of the list comprehension.

`fmap` is used here because `Event` is a `Functor` therefore we can't really apply standard functions such as `take` and `+12` right?

> [@yaxu](#):
>
> Then I made this function that allows you to group any co-occuring events and work on them together

So here I understand that when we `stack` something as in the case of chords, Tidal creates an `Event` for every single note in the stack and these `Event`s happen to play in the same `Part`, i.e. they are scheduled to be simultaneous?  
(Plus I got a bit lost inside the function TBH.)

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [21 May 2020 22:13 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/5 "2020-05-21T22:13:10Z")

</div>

> [@mattia.paterna](#):
>
> `fmap` is used here because `Event` is a `Functor` therefore we can't really apply standard functions such as `take` and `+12` right?

Yep! The fmap is there to do something to the value inside the event.

> [@mattia.paterna](#):
>
> So here I understand that when we `stack` something as in the case of chords, Tidal creates an `Event` for every single note in the stack and these `Event` s happen to play in the same `Part` , i.e. they are scheduled to be simultaneous?

Yes, so if you played two chords at the same time, this function would treat them as a single chord.

At this point tidal isn't creating any events, but composing a function for creating events.

> [@mattia.paterna](#):
>
> (Plus I got a bit lost inside the function TBH.)

Yes there's a lot going on here..

---

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [21 May 2020 22:40 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/6 "2020-05-21T22:40:56Z")

</div>

> [@yaxu](#):
>
> Yes there's a lot going on here..

I can see couple of things in there though:

- you are using `withEvents`, which (if I am correct) should apply a function to the input pattern
- the function that you want to apply is `munge`, which
  - sorts a list of `Event`s from lowest to highest (I assume with respect of time) based on `whole` (no real idea about it)
  - groups the resulting list given some predicate (and `whole` is here again)
  - applies the function coming all the way from `withEvents` and concatenate the result

> [@yaxu](#):
>
> Then bring it together:
> 
> ```haskell
> invert :: Num b => Int -> Pattern b -> Pattern b
> invert = withFriends . inversion
> 
> ```

but where is `eventInversion` gone?

---

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [21 May 2020 22:47 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/7 "2020-05-21T22:47:21Z")

</div>

I think this relates to what I was saying somewhere else in the club about the struggle to making things work.  
What I experience is that I sometimes (hopefully) learn something new in Haskell, e.g. list comprehension. A lot of ideas come on how to tweak this list into that - but then I try to write something and it almost never works because either the function input is not what it should be or the output is not what Tidal wants.

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [21 May 2020 23:38 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/8 "2020-05-21T23:38:31Z")

</div>

Oops that should be -  
`invert = withFriends . eventInversion`

A lot of haskell documentation focuses on working with lazy lists, which isn't often useful with tidal. Generally they're awesome but I'd say that lists are a kind of code smell with tidal.

---

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [22 May 2020 03:50 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/9 "2020-05-22T03:50:09Z")

</div>

> [@yaxu](#):
>
> I'd say that lists are a kind of code smell with tidal

Definitely interested in knowing more about your point of view.

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [22 May 2020 10:02 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/10 "2020-05-22T10:02:31Z")

</div>

It's just that Tidal paradigm is about functions of time, not data structures like lists.. About defining behaviour and not procedures.

---

<div class="post-metadata">

**Author:** ![loopology](https://uzu.lurk.org/user_avatar/uzu.lurk.org/loopology/32/60_2.png) [@loopology](https://uzu.lurk.org/u/loopology)\
**Post date:** [22 May 2020 20:42 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/11 "2020-05-22T20:42:55Z")

</div>

Thanks a lot for taking the time and energy to explain this, Alex @yaxu. And thanks to Mattia @mattia.paterna for asking. That's going to give me a lot to think about...

---

<div class="post-metadata">

**Author:** ![mattia.paterna](https://uzu.lurk.org/user_avatar/uzu.lurk.org/mattia.paterna/32/112_2.png) [@mattia.paterna](https://uzu.lurk.org/u/mattia.paterna)\
**Post date:** [23 May 2020 14:53 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/12 "2020-05-23T14:53:00Z")

</div>

you're welcome @loopology!  
I've been trying really hard to get deeper into the innards and every time I see this kind of discussion I jump in straight away.

@yaxu I apologise in advance because I'll probably be asking many more times in the next weeks about Tidal paradigm as it is not clear yet to me 🙂

---

<div class="post-metadata">

**Author:** ![loopology](https://uzu.lurk.org/user_avatar/uzu.lurk.org/loopology/32/60_2.png) [@loopology](https://uzu.lurk.org/u/loopology)\
**Post date:** [24 May 2020 16:37 UTC](https://uzu.lurk.org/t/working-with-groups-of-co-occuring-events/1098/13 "2020-05-24T16:37:06Z")

</div>

@mattia.paterna, please tag me when you do, as I'm on the same track, even if behind you 🙂
