Type signatures

From TidalCycles userbase
Revision as of 02:41, 24 November 2018 by Munshkr (talk | contribs) (fix typos)
Jump to: navigation, search

In Haskell (which Tidal lives in), a type signature tells you what kind of thing a value or function is. They're particularly useful for finding out what a function expects from you, and what it gives back.

You can find out the type of a function is with :t , for example to find out the type signature for rev, you could type :t rev into your editor, and evaluate it. You'll see this in the output window:

rev :: Pattern a -> Pattern a

That's quite simple, it tells you that it takes a pattern as input, and gives you back a pattern as output. Let's have a look at the fast function, via :t fast:

fast :: Pattern Time -> Pattern a -> Pattern a

That's a bit more complicated, there's three patterns there. The last one is always the output, and the ones preceding it are the inputs. So fast takes a pattern of time, another pattern, and gives you a pattern in return. That makes some sense too, the first parameter says how fast it should go in terms of time, and can be patterned. The second parameter is the pattern that is going to be made faster, but it doesn't say what kind of pattern it is, it just says Pattern a, and the same with the output. It was the same earlier with rev. What's going on?

Well the a in Pattern a is unconstrained - it can be whatever you like. So the rev function can work on any kind of pattern. This is because rev doesn't deal with any particular values, it just manipulates time.

So a is a kind of wildcard here, Pattern a is also the type of the input. This means that if you give it a pattern of integers, you are guaranteed to get a pattern of integers back. So you can swap that a for another type but only if you swap all instances of it for the same type.

A more complicated example is every:

every :: Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a

Now, every takes three parameters, a whole number of cycles, a function to apply to a pattern, and the pattern itself. We can see that the first parameter is a pattern of integers, or whole numbers, fine. The second parameter is stranger - (Pattern a -> Pattern a). This is how functions that are parameters are shown - wrapped in parenthesis. We can see from this that the second parameter is a function, that takes a pattern as input and gives a pattern as input. If we look back at the type signature of rev, it's pretty clear that we could give that as this second parameter, as the types match.. Indeed it's quite common to do every 3 rev (s "bd sn"), for example.

Hopefully that gives you some insight into how to read type signatures. They're really useful for understanding how to use functions, even without reading documentation.

Feel free to add any questions to the discussion page.