I'd say some use of the struct function could do the trick, but from your example I'm failing to infer how <~> worked precisely. Does a6*45 give rise to 5 copies of a6*8 because the euclidean division of 45 by 8 yields 5? If so, how comes g6*8 is present at all?
Could you direct us to where you found this place of documentation?

The "preplace" family of functions has always been a little weird since internally they force Patterns to act as lists and then turn things back into a Pattern, and sometimes this has strange or unpredictable results.

But I think I got something working. Had to change some details slightly because of "Overlapping Instance" problems so there might be some issues. I'll test it out a bit and submit a PR if it seems to work but for now you can copy/paste this to get the <~> operator working again:

import Data.List (sortBy)
prrw :: (a -> b -> c) -> Int -> (Time, Time) -> Pattern a -> Pattern b -> Pattern c
prrw f rot (blen, vlen) beatPattern valuePattern =
let
ecompare ev1 ev2 = compare (start $ part ev1) (start $ part ev2)
beats = sortBy ecompare $ queryArc beatPattern (Arc 0 blen)
values = fmap value . sortBy ecompare $ queryArc valuePattern (Arc 0 vlen)
cycles = blen * (fromIntegral $ lcm (length beats) (length values) `div` (length beats))
in
_slow cycles $ stack $ zipWith
(\ev v -> ((start $ part ev) `rotR`) $ _fastGap (1 / ((stop $ part ev) - (start $ part ev))) $ pure (f (value ev) v))
(sortBy ecompare $ queryArc (_fast cycles $ beatPattern) (Arc 0 blen))
(drop (rot `mod` length values) $ cycle values)
prr :: Int -> (Time, Time) -> Pattern String -> Pattern a -> Pattern a
prr = prrw (flip const)
preplace = prr 0
(<~>) = preplace (1,1)

I don't think so, can you post a full example of what gave the error?

In the long run, and for consistency, it may be better to switch the preplace-style functions so that they use Pattern Bool so you'd use "t*8" <~> "a6*45 e6*8" instead of putting "x" characters in there.

Nevermind, I just forgot to parse the type signatures, and they turn out to be important, now it's working!
Incredible job with this function, and +1 for the bool mask, it makes a lot of sense