TidalCycles (aka Tidal) is a Haskell DSL for making (usually musical) pattern.
I’ve put a lot of time into Tidal the last couple of months, starting with preparation for an advanced tidal workshop in Tokyo, but things got out of hand and ended with a rewrite of its innards, solving some long-standing issues. It feels like I’ve only recently grown to understand what tidal really is in the process of writing (and rewriting) it over many years, and I’ve finally got to put that understanding into action. I’ve had some really useful feedback from the Haskell community in the past and so thought I’d write this post as an effort at getting feedback on this latest iteration.
Tidal is all about pattern. I’ve tried to explain what this means in terms of types in this wiki page – What is a pattern?
That page talks through the first bit of Sound.Tidal.Pattern, which also contains applicative and monad instances for patterns. The previous attempt at these didn’t conform to the applicative and monad laws, but these new versions hopefully are much closer to the mark. I’ve found though that <*>
and join
aren’t enough for Tidal. I also need <*
for where pattern structure comes from the left, and *>
for where it comes from the right, where <*>
comes from both sides. Similarly, as well as join
(which I’m calling unwrap
) I needed to make innerJoin
and outerJoin
. You could have a look at the Combining pattern structure wiki page to get an insight into why these are needed.
Other modules I invite you to look at include Sound.Tidal.Core, Sound.Tidal.Control, Sound.Tidal.UI, and the rest, roughly in that order.
Tidal is my only real haskell project and I’ve learned haskell through (admittedly many years) of writing/rewriting it, so all insights much appreciated!
There has been a couple of instances where Haskell fans have been immediately turned off by Tidal, I think because of the large amount of strings used in Tidal code. These strings are actually overloaded, a parser in Sound.Tidal.ParseBP silently turns them into well-typed patterns (which are functions of time, and not strings or lists). Anything in those strings could be expressed in Haskell code, but with a _lot_ more keypresses. This mini-language is heavily influenced by the representation of cyclic structures Indian classical music (i.e. Bernard Bel’s BP2). I’d really like to get to the bottom of why people don’t like the look of these strings though, and whether there is a better alternative.
All feedback, suggestions and criticism much appreciated!