Random integer oscillator

I suppose this question fits the Innards category only partially. I am looking for a way to generate a random integer each cycle and assign it as an argument to a function, with transitions between arising patterns, ideally, being continuous. With functions that take Fractional arguments, perlin does the trick, as in the following example:

  $ slow (perlin)
  $ note "b5" # "superpiano"
  + up "-7 -5 0 2 3 -5 -7 2 0 -5 3 2".

However, with functions with integer arguments, for example spin, this of course doesn't work. I thought of quantising the Perlin noise:

  $ spin (quantise 1 $ perlin*100)
  $ note "b5" # "superpiano"
  + up "-7 -5 0 2 3 -5 -7 2 0 -5 3 2"

But this results in an error:

    • No instance for (RealFrac Int) arising from a use of ‘quantise’
    • In the expression: quantise 1
      In the first argument of ‘spin’, namely
        ‘(quantise 1 $ perlin * 100)’
      In the expression: spin (quantise 1 $ perlin * 100)

    • No instance for (Fractional Int) arising from a use of ‘perlin’
    • In the first argument of ‘(*)’, namely ‘perlin’
      In the second argument of ‘($)’, namely ‘perlin * 100’
      In the first argument of ‘spin’, namely
        ‘(quantise 1 $ perlin * 100)’.

I am not familiar enough with the inner workings of Tidal to understand the error. A similar problem was discussed on this forum a while back (cf. Quantise type), but the solution offered doesn't work in this case. Does anybody have an idea, wherein the problem might lie?

Additionally, I am wondering whether there is in general a way to change the argument of a certain function on each cycle, for example to increment it by a certain number?

Sometimes I've worked around this by using choose or chooseBy to randomly select from a list of integers. I thing irand might also work with segment the way you have it set up with perlin

Yep, as @xinniw has said, segment and irand will work - however, you may even be able to drop segment:

d1 $
  spin (irand 8)
  $ note "b5" # s "sprvibe"
  + up "-7 -5 0 2 3 -5 -7 2 0 -5 3 2"

Also see:

Just to quickly touch on quantise, note how it returns the same type you feed it, and therefore cannot be used to convert types:

quantise :: (Functor f, RealFrac b) => b -> f b -> f b

And if you bump into similar type errors in the future, or are searching for functions which work with various inputs (in various orders) or produce various outputs, don’t forget that Hoogle is always your friend.


Thank you for your helpful replies! I've found the solution for converting RealFrac patterns into Integer ones in an older thread (cf. Rounding Float patterns - #3 by yaxu):

  $ spin (round <$> perlin*100)
  $ note "b5" # "superpiano"
  + up "-7 -5 0 2 3 -5 -7 2 0 -5 3 2".

The round function was exactly what I was looking for, although I'm unsure how the operator <$> functions. Time to finally dig into how Tidal is implemented, I suppose:)


To perhaps save you some digging, at least until you become even more curious:

<$> is a part of Haskell, rather than Tidal, and is an infix operator alternative to the function called fmap. You can think of fmap / <$> as applying a function to each of the values contained within a structure, resulting in a new, similarly-shaped, structure containing the results.

The syntax of <$> provides an analogue to that of function application. Consider the following examples, starting with a few that round a single value (using various available notations,) moving on to one which rounds all of the values in a list, and then ending with one which, given a pattern, returns a new pattern that, when queried, produces the same events as the original pattern would but with the value of each event transformed by the function provided:

  • round 100.42
  • round (100 + 0.42)
  • round $ 100 + 0.42 ($ is a Haskell function you’ve seen a lot in Tidal. It provides an infix notation for function application, and is most often used to avoid parentheses.)
  • round <$> [100.42, 37.2, 94.8]
  • round <$> perlin * 100

As a jumping-off point if you’re curious to continue, check out the docs for <$> here.