## Patterns are the time of numbers

Ok this post is going to look quite dry, but is actually very exciting, at least for users of TidalCycles. So first here’s a video demonstrating the simplified syntax the below blurb will allow in a future version (version 1.0, which will probably be released soon after the upcoming 0.9).

If you want to see more videos like this check the playlists on the TidalCycles youtube channel.

Anyway.. Something I’ve noticed at Tidal workshops is that beginners have problems with this sort of code:
`density 2 "1 2 3 4"`
There’s the pattern `1 2 3 4`, denoted by quotes, and the number `2` without quotes. This says ‘make the pattern twice as dense’, so you end up with this every cycle: `1 2 3 4 1 2 3 4`.

Fairly straightforward, but why is the `2` a number, not a pattern? With more complicated, higher-order patterns this becomes increasingly unclear. There are ways to treat that number like a pattern:

`spread' (density) "2 5" \$ "1 2 3 4"`
or ..
`do n <- "2 5"`
`   density n "1 2 3 4"`

… but now you’re converting between numbers and patterns of numbers instead of engaging with the music you’re making.

So I asked about this on haskell-art, in particular how to make it so a function like `density` could take either a number, or a pattern of numbers. One suggestion from Henning Thielemann was surprising – that Tidal’s `Pattern` type could be defined as a Haskell `Num`ber.

To cut this short it turned out that simply by evaluating a small amount of very simple code[1], Tidal’s syntax suddenly becomes far more expressive.

`d1 \$ sound "bass3" # speed "1.2"`

you can just do
`d1 \$ sound "bass3" # speed 1.2`

`d1 \$ sound "bass3*4" # speed (scale 1.2 3.2 \$ ((+) <\$> (slow 4 tri1) <*> sine1))`
you can just do:
`d1 \$ sound "bass3*4" # speed ((slow 4 tri1) + sine1 * 2 + 1.2)`

`d1 \$ up (every 3 ((+12) <\$>) "1 8 [7 ~ 4]") # sound "bd"`
it’s simply:
`d1 \$ up (every 3 (+12) "1 8 [7 ~ 4]") # sound "bd"`
and with a quick re-jig of the definition of functions like `density`:

`d1 \$ n ((+) <\$> ((+) <\$> "1 2 3" <*> slow 3 "0 1") <*> slow 2 "3 1") # sound "voodoo"`
it’s:
`d1 \$ n ("1 2 3" + slow 3 "0 1" + slow 2 "3 1") # sound "voodoo"`

and much more…

By redefining `density` and friends, e.g.:

`let density tp p = unwrap \$ (\tv -> withResultTime (/ tv) \$ withQueryTime (* tv) p) <\$> tp`

It’s then possible to fulfil my original aim:

`d1 \$ density "1 [2 3] [1 3]/2" \$ sound "bd [sn:2 mt]/2"`
while still supporting the original syntax:
`d1 \$ density 1.5 \$ sound "bd [sn:2 mt]/2"`

Basically, it turns out that if you let Haskell treat patterns of numbers as numbers, it provides extremely expressive means for working with them. This makes sense — patterns of numbers are numbers, just numbers which are polyphonic, and vary over (rational) time.

Lovely. This is a huge and unexpected win, which greatly simplifies pattern combination and manipulation, in the process greatly extending the possibilities that are within reach of a few keystrokes. This renews my suspicion that Haskell is full of much wondrous stuff just waiting to be discovered..

[1] Here’s that ‘small amount of very simple code’, if you want to try this at home:

```instance Num a => Num (Pattern a) where negate = fmap negate (+) = liftA2 (+) (*) = liftA2 (*) fromInteger = pure . fromInteger abs = fmap abs signum = fmap signum```

```instance (Fractional a) => Fractional (Pattern a) where fromRational = pure . fromRational (/) = liftA2 (/)```

### 2 thoughts on “Patterns are the time of numbers”

1. Well done to you and Henning (one hell of a Haskeller!)!

2. Jabu says:

This is quite brilliant! Well done guys!

This site uses Akismet to reduce spam. Learn how your comment data is processed.