Ints made sense to me as a representation of ‘score time’. A series of slots where things can go. To get ‘performance time’ e.g. swing, I add floating point offsets to that. I have to think more on this though, looking forward to learning more about FRP.

I went for what you point out is ziplist-like behaviour so I could effect particular ‘levels’ in a polymetric pattern. I think that should probably be done in a more explicit way though. I’ll respond to your blog post properly soon Ryan.

]]>I don’t like your applicative instance (it is similar to the applicative instance for zip-lists); I think the applicative instance for regular lists makes more sense. The difference is that [(+1),(+2)] [3,4], for regular lists is [4,5,5,6], but for ziplists is [4,6]. Still, I can see how you might want to go that direction.

However, you also give special treatment to the “f” argument; if it’s short, the resulting list gets cycled, but if the “x” argument is short, it doesn’t. I am pretty sure that violates one of the applicative functor laws. (f <*> pure x = pure ($x) <*> f).

]]>There is a hazard in using functions as your representation that took me many years to grok. Ironically, functional programming is biased against functions and in favor of data structures, in that data structures are automatically memoized, while functions are not.

Typically FRP uses continuous time, unlike your choice of Int, but that choice is not fundamental. BTW, did you consider continuous “time” here? Whether time or space, continuous is usually more composable than discrete. See brief related remarks at http://conal.net/blog/posts/early-inspirations-and-new-directions-in-functional-reactive-programming/ .

]]>I did make Pattern an Applicative instance on the way to the Monad instance:

> instance Applicative Pattern where > pure a = loop $ [a] > pf@(Pattern _ n) <*> pa@(Pattern _ n') = Pattern l (lcm n n') > where l n = map (\(a, b) -> (a b)) $ zip (cycle (at pf n)) (at pa n)

… although at the moment I’m not sure what that buys me. Much to read!

I’ll have a go at Conal’s paper for sure Ryan, interesting that what I’m trying to do is somehow related to FRP, I had no idea.

Good point about a -> Pattern b being useless leadnose. I was thinking of functions from some particular type to some other particular type, rather than to the same type, but of course they’d have a less general signature than that. After too long programming perl, this is all still coming together in my head…

]]>a -> Pattern b

doesn’t really make sense, since it would consume anything, and produce a pattern of some other, totally unrelated type. Also not everything needs to be made into a monad (since not everything is one), you can combine things in other ways too. That said, good luck and have fun using Haskell to make music :) This might be of interest to you: http://www.haskell.org/haskore/ ]]>

Also, you may want to look at the Reactive library; I am seeing some striking similarities between what you are defining and that library. There’s a paper about the library here: http://conal.net/papers/push-pull-frp/

]]>fmapPattern :: (a -> b) -> Pattern a -> Pattern b

returnPattern :: a -> Pattern a

joinPattern :: Pattern (Pattern a) -> Pattern a

instance Functor Pattern where fmap = fmapPattern

instance Monad Pattern where

return = returnPattern

m >>= f = joinPattern (fmap f m)

I think it’s likely that Pattern is only an applicative functor, and not a monad:

instance Applicative Pattern where

pure x = loop [x]

(Pattern fs pf) (Pattern xs px) = Pattern fxs (pf*px) where

fxs n = fs n $ xs n

No I haven’t, I will take a look though, cheers for the tip. I’ve been meaning to have a proper look at supercollider’s pattern library too, which I think is based on HMSL.

]]>