diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,26 @@
 # TidalCycles log of changes
 
+
+## 1.0.8 (trying to get back to doing these, 
+## see also https://tidalcycles.org/index.php/Changes_in_Tidal_1.0.x 
+## for earlier stuff)
+
+* Add 'to', 'toArg' and 'from' controls for new superdirt routing experiments - @telephon
+* Fixes for squeezeJoin (nee unwrap') - @bgold-cosmos
+* Simplify `cycleChoose`, it is now properly discrete (one event per cycle) - @yaxu
+* The return of `<>`, `infix alias for overlay` - @yaxu
+* Fix for `wedge` to allow 0 and 1 as first parameter  - @XiNNiW
+* Support for new spectral fx - @madskjeldgaard
+* Fix for _euclidInv - @dktr0
+* `chordList` for listing chords - @XiNNiW
+* new function `soak` - @XiNNiW
+* tempo fixes - @bgold-cosmos
+* miniTidal developments - @dktr0
+* potentially more efficient euclidean patternings - @dktr0
+* unit tests for euclid - @yaxu
+* fix for `sometimesBy` - @yaxu
+
+
 ## 0.9.10 (and earlier missing versions from this log)
 
 * arpg, a function to arpeggiate
diff --git a/src/Sound/Tidal/Chords.hs b/src/Sound/Tidal/Chords.hs
--- a/src/Sound/Tidal/Chords.hs
+++ b/src/Sound/Tidal/Chords.hs
@@ -110,13 +110,13 @@
               ("maj", major),
               ("minor", minor),
               ("min", minor),
+              ("aug", aug),
+              ("dim", dim),
               ("major7", major7),
               ("maj7", major7),
               ("dom7", dom7),
               ("minor7", minor7),
               ("min7", minor7),
-              ("aug", aug),
-              ("dim", dim),
               ("dim7", dim7),
               ("one", one),
               ("1", one),
@@ -181,4 +181,7 @@
 
 chordL :: Num a => Pattern String -> Pattern [a]
 chordL p = (\name -> fromMaybe [] $ lookup name chordTable) <$> p
+
+chordList :: String
+chordList = unwords $ map fst (chordTable :: [(String, [Int])])
 
diff --git a/src/Sound/Tidal/Control.hs b/src/Sound/Tidal/Control.hs
--- a/src/Sound/Tidal/Control.hs
+++ b/src/Sound/Tidal/Control.hs
@@ -59,13 +59,13 @@
 chop = tParam _chop
 
 chopArc :: Arc -> Int -> [Arc]
-chopArc (Arc s e) n = map (\i -> (Arc (s + (e-s)*(fromIntegral i/fromIntegral n)) (s + (e-s)*((fromIntegral $ i+1)/fromIntegral n)))) [0 .. n-1]
+chopArc (Arc s e) n = map (\i -> Arc (s + (e-s)*(fromIntegral i/fromIntegral n)) (s + (e-s)*(fromIntegral (i+1) / fromIntegral n))) [0 .. n-1]
 
 _chop :: Int -> ControlPattern -> ControlPattern
-_chop n p = withEvents (concatMap chopEvent) p
+_chop n = withEvents (concatMap chopEvent)
   where -- for each part,
         chopEvent :: Event ControlMap -> [Event ControlMap]
-        chopEvent (Event w p' v) = map (\a -> chomp v (length $ chopArc w n) a) $ arcs w p'
+        chopEvent (Event w p' v) = map (chomp v (length $ chopArc w n)) $ arcs w p'
         -- cut whole into n bits, and number them
         arcs w' p' = numberedArcs p' $ chopArc w' n
         -- each bit is a new whole, with part that's the intersection of old part and new whole
@@ -83,8 +83,8 @@
                 e = fromMaybe 1 $ do v' <- Map.lookup "end" v
                                      getF v'
                 d = e-b
-                b' = (((fromIntegral i)/(fromIntegral n')) * d) + b
-                e' = (((fromIntegral $ i+1)/(fromIntegral n')) * d) + b
+                b' = ((fromIntegral i/fromIntegral n') * d) + b
+                e' = ((fromIntegral (i+1) / fromIntegral n') * d) + b
 
 {-
 -- A simpler definition than the above, but this version doesn't chop
@@ -125,11 +125,11 @@
 striate = tParam _striate
 
 _striate :: Int -> ControlPattern -> ControlPattern
-_striate n p = fastcat $ map (\i -> offset i) [0 .. n-1]
-  where offset i = (mergePlayRange ((fromIntegral i / fromIntegral n), (fromIntegral (i+1) / fromIntegral n))) <$> p
+_striate n p = fastcat $ map offset [0 .. n-1]
+  where offset i = mergePlayRange (fromIntegral i / fromIntegral n, fromIntegral (i+1) / fromIntegral n) <$> p
 
 mergePlayRange :: (Double, Double) -> ControlMap -> ControlMap
-mergePlayRange (b,e) cm = Map.insert "begin" (VF $ (b*d')+b') $ Map.insert "end" (VF $ (e*d')+b') $ cm
+mergePlayRange (b,e) cm = Map.insert "begin" (VF $ (b*d')+b') $ Map.insert "end" (VF $ (e*d')+b') cm
   where b' = fromMaybe 0 $ Map.lookup "begin" cm >>= getF
         e' = fromMaybe 1 $ Map.lookup "end" cm >>= getF
         d' = e' - b'
@@ -158,9 +158,9 @@
 striate' = striateBy
 
 _striateBy :: Int -> Double -> ControlPattern -> ControlPattern
-_striateBy n f p = fastcat $ map (\i -> offset (fromIntegral i)) [0 .. n-1]
+_striateBy n f p = fastcat $ map (offset . fromIntegral) [0 .. n-1]
   where offset i = p # P.begin (pure (slot * i) :: Pattern Double) # P.end (pure ((slot * i) + f) :: Pattern Double)
-        slot = (1 - f) / (fromIntegral n)
+        slot = (1 - f) / fromIntegral n
 
 
 
@@ -177,7 +177,7 @@
 gap = tParam _gap
 
 _gap :: Int -> ControlPattern -> ControlPattern 
-_gap n p = (_fast (toRational n) $ cat [pure 1, silence]) |>| ( _chop n p)
+_gap n p = _fast (toRational n) (cat [pure 1, silence]) |>| _chop n p
 
 {- |
 `weave` applies a function smoothly over an array of different patterns. It uses an `OscPattern` to
@@ -188,7 +188,7 @@
 @
 -}
 weave :: Time -> ControlPattern -> [ControlPattern] -> ControlPattern
-weave t p ps = weave' t p (map (\x -> (x #)) ps)
+weave t p ps = weave' t p (map (#) ps)
 
 
 {- | `weaveWith` is similar in that it blends functions at the same time at different amounts over a pattern:
@@ -199,7 +199,7 @@
 -}
 weaveWith :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
 weaveWith t p fs | l == 0 = silence
-              | otherwise = _slow t $ stack $ map (\(i, f) -> (fromIntegral i % l) `rotL` (_fast t $ f (_slow t p))) (zip [0 :: Int ..] fs)
+              | otherwise = _slow t $ stack $ map (\(i, f) -> (fromIntegral i % l) `rotL` _fast t (f (_slow t p))) (zip [0 :: Int ..] fs)
   where l = fromIntegral $ length fs
 
 weave' :: Time -> Pattern a -> [Pattern a -> Pattern a] -> Pattern a
@@ -219,7 +219,7 @@
 @
 -}
 interlace :: ControlPattern -> ControlPattern -> ControlPattern
-interlace a b = weave 16 (P.shape $ (sine * 0.9)) [a, b]
+interlace a b = weave 16 (P.shape (sine * 0.9)) [a, b]
 
 {-
 {- | Just like `striate`, but also loops each sample chunk a number of times specified in the second argument.
@@ -249,8 +249,8 @@
 
 slice :: Pattern Int -> Pattern Int -> ControlPattern -> ControlPattern
 slice pN pI p = P.begin b # P.end e # p
-  where b = (\i n -> (div' i n)) <$> pI <* pN
-        e = (\i n -> (div' i n) + (div' 1 n)) <$> pI <* pN
+  where b = div' <$> pI <* pN
+        e = (\i n -> div' i n + div' 1 n) <$> pI <* pN
         div' num den = fromIntegral (num `mod` den) / fromIntegral den
 
 _slice :: Int -> Int -> ControlPattern -> ControlPattern
@@ -305,13 +305,13 @@
 -}
 
 smash :: Pattern Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap
-smash n xs p = slowcat $ map (\x -> slow x p') xs
+smash n xs p = slowcat $ map (`slow` p') xs
   where p' = striate n p
 
 {- | an altenative form to `smash` is `smash'` which will use `chop` instead of `striate`.
 -}
 smash' :: Int -> [Pattern Time] -> ControlPattern -> Pattern ControlMap
-smash' n xs p = slowcat $ map (\x -> slow x p') xs
+smash' n xs p = slowcat $ map (`slow` p') xs
   where p' = _chop n p
 
 
@@ -335,9 +335,9 @@
 stut = tParam3 _stut
 
 _stut :: Integer -> Double -> Rational -> ControlPattern -> ControlPattern
-_stut count feedback steptime p = stack (p:(map (\x -> (((x%1)*steptime) `rotR` (p |* P.gain (pure $ scalegain (fromIntegral x))))) [1..(count-1)]))
-  where scalegain x
-          = ((+feedback) . (*(1-feedback)) . (/(fromIntegral count)) . ((fromIntegral count)-)) x
+_stut count feedback steptime p = stack (p:map (\x -> ((x%1)*steptime) `rotR` (p |* P.gain (pure $ scalegain (fromIntegral x)))) [1..(count-1)])
+  where scalegain
+          = (+feedback) . (*(1-feedback)) . (/ fromIntegral count) . (fromIntegral count -)
 
 {- | Instead of just decreasing volume to produce echoes, @stut'@ allows to apply a function for each step and overlays the result delayed by the given time.
 
@@ -366,7 +366,7 @@
 
 _cX :: (Arc -> Value -> [Event a]) -> [a] -> String -> Pattern a
 _cX f ds s = Pattern Analog $
-               \(State a m) -> maybe (map (\d -> (Event a a d)) ds) (f a) $ Map.lookup s m
+               \(State a m) -> maybe (map (Event a a) ds) (f a) $ Map.lookup s m
 
 _cF :: [Double] -> String -> Pattern Double
 _cF = _cX f
@@ -410,7 +410,7 @@
 _cP ds s = innerJoin $ _cX f ds s
   where f a (VI v) = [Event a a (parseBP_E $ show v)]
         f a (VF v) = [Event a a (parseBP_E $ show v)]
-        f a (VS v) = [Event a a (parseBP_E $ v)]
+        f a (VS v) = [Event a a (parseBP_E v)]
 cP :: (Enumerable a, Parseable a) => Pattern a -> String -> Pattern a
 cP d = _cP [d]
 cP_ :: (Enumerable a, Parseable a) => String -> Pattern a
diff --git a/src/Sound/Tidal/Core.hs b/src/Sound/Tidal/Core.hs
--- a/src/Sound/Tidal/Core.hs
+++ b/src/Sound/Tidal/Core.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
 
 module Sound.Tidal.Core where
 
@@ -25,7 +25,7 @@
 -- | @sine@ returns a 'Pattern' of continuous 'Fractional' values following a
 -- sinewave with frequency of one cycle, and amplitude from 0 to 1.
 sine :: Fractional a => Pattern a
-sine = sig $ \t -> ((sin_rat $ (pi :: Double) * 2 * (fromRational t)) + 1) / 2
+sine = sig $ \t -> (sin_rat ((pi :: Double) * 2 * fromRational t) + 1) / 2
   where sin_rat = fromRational . toRational . sin
 
 -- | @cosine@ is a synonym for @0.25 ~> sine@.
@@ -47,7 +47,7 @@
 -- | @square@ is the equivalent of 'sine' for square waves.
 square :: (Fractional a) => Pattern a
 square = sig $
-         \t -> fromIntegral $ ((floor $ (mod' (fromRational t :: Double) 1) * 2) :: Integer)
+       \t -> fromIntegral ((floor $ mod' (fromRational t :: Double) 1 * 2) :: Integer)
 
 -- | @envL@ is a 'Pattern' of continuous 'Double' values, representing
 -- a linear interpolation between 0 and 1 during the first cycle, then
@@ -63,11 +63,11 @@
 
 -- | 'Equal power' version of 'env', for gain-based transitions
 envEq :: Pattern Double
-envEq = sig $ \t -> sqrt (sin (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))
+envEq = sig $ \t -> sqrt (sin (pi/2 * max 0 (min (fromRational (1-t)) 1)))
 
 -- | Equal power reversed
 envEqR :: Pattern Double
-envEqR = sig $ \t -> sqrt (cos (pi/2 * (max 0 $ min (fromRational (1-t)) 1)))
+envEqR = sig $ \t -> sqrt (cos (pi/2 * max 0 (min (fromRational (1-t)) 1)))
 
 -- ** Pattern algebra
 
@@ -118,11 +118,11 @@
 a  %| b = mod' <$> a *> b
 
 (|>|) :: (Applicative a, Unionable b) => a b -> a b -> a b
-a |>| b = (flip union) <$> a <*> b
+a |>| b = flip union <$> a <*> b
 (|> ) :: Unionable a => Pattern a -> Pattern a -> Pattern a
-a |>  b = (flip union) <$> a <* b
+a |>  b = flip union <$> a <* b
 ( >|) :: Unionable a => Pattern a -> Pattern a -> Pattern a
-a  >| b = (flip union) <$> a *> b
+a  >| b = flip union <$> a *> b
 
 (|<|) :: (Applicative a, Unionable b) => a b -> a b -> a b
 a |<| b = union <$> a <*> b
@@ -222,16 +222,20 @@
     where total = sum $ map fst tps
           arrange :: Time -> [(Time, Pattern a)] -> [(Time, Time, Pattern a)]
           arrange _ [] = []
-          arrange t ((t',p):tps') = (t,t+t',p):(arrange (t+t') tps')
+          arrange t ((t',p):tps') = (t,t+t',p) : arrange (t+t') tps'
 
 -- | 'overlay' combines two 'Pattern's into a new pattern, so that
 -- their events are combined over time. 
 overlay :: Pattern a -> Pattern a -> Pattern a
 -- Analog if they're both analog
-overlay p@(Pattern Analog _) p'@(Pattern Analog _) = Pattern Analog $ \st -> (query p st) ++ (query p' st)
+overlay p@(Pattern Analog _) p'@(Pattern Analog _) = Pattern Analog $ \st -> query p st ++ query p' st
 -- Otherwise digital. Won't really work to have a mixture.. Hmm
-overlay p p' = Pattern Digital $ \st -> (query p st) ++ (query p' st)
+overlay p p' = Pattern Digital $ \st -> query p st ++ query p' st
 
+-- | An infix alias of @overlay@
+(<>) :: Pattern a -> Pattern a -> Pattern a
+(<>) = overlay
+
 -- | 'stack' combines a list of 'Pattern's into a new pattern, so that
 -- their events are combined over time.
 stack :: [Pattern a] -> Pattern a
@@ -264,7 +268,7 @@
 
 _fast :: Time -> Pattern a -> Pattern a
 _fast r p | r == 0 = silence
-          | r < 0 = rev $ _fast (0-r) p
+          | r < 0 = rev $ _fast (negate r) p
           | otherwise = withResultTime (/ r) $ withQueryTime (* r) p
 
 -- | Slow down a pattern by the given time pattern
@@ -292,8 +296,7 @@
       mapParts (mirrorArc (midCycle $ arc st)) $
       map makeWholeRelative
       (query p st
-        {arc =
-            (mirrorArc (midCycle $ arc st) (arc st))
+        {arc = mirrorArc (midCycle $ arc st) (arc st)
         })
     }
   where makeWholeRelative :: Event a -> Event a
@@ -303,7 +306,7 @@
         makeWholeAbsolute (Event (Arc s e) p'@(Arc s' e') v) =
           Event (Arc (s'-e) (e'+s)) p' v
         midCycle :: Arc -> Time
-        midCycle (Arc s _) = (sam s) + 0.5
+        midCycle (Arc s _) = sam s + 0.5
         mapParts :: (Arc -> Arc) -> [Event a] -> [Event a]
         mapParts f es = (\(Event w p' v) -> Event w (f p') v) <$> es
         -- | Returns the `mirror image' of a 'Arc' around the given point in time
@@ -328,7 +331,7 @@
 
 zoomArc :: Arc -> Pattern a -> Pattern a
 zoomArc (Arc s e) p = splitQueries $
-  withResultArc (mapCycle ((/d) . (subtract s))) $ withQueryArc (mapCycle ((+s) . (*d))) p
+  withResultArc (mapCycle ((/d) . subtract s)) $ withQueryArc (mapCycle ((+s) . (*d))) p
      where d = e-s
 
 -- | @fastGap@ is similar to 'fast' but maintains its cyclic
@@ -372,12 +375,12 @@
 every' np op f p = do { n <- np; o <- op; _every' n o f p }
 
 _every' :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
-_every' n o f = when ((== o) . (`mod` n)) f
+_every' n o = when ((== o) . (`mod` n))
 
 -- | @foldEvery ns f p@ applies the function @f@ to @p@, and is applied for
 -- each cycle in @ns@.
 foldEvery :: [Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
-foldEvery ns f p = foldr ($) p (map (\x -> _every x f) ns)
+foldEvery ns f p = foldr (`_every` f) p ns
 
 {-|
 Only `when` the given test function returns `True` the given pattern
diff --git a/src/Sound/Tidal/EspGrid.hs b/src/Sound/Tidal/EspGrid.hs
--- a/src/Sound/Tidal/EspGrid.hs
+++ b/src/Sound/Tidal/EspGrid.hs
@@ -17,16 +17,16 @@
   n :: Integer <- datum_integral (d!!4)
   let nanos = (t1*1000000000) + t2
   return $ \t -> t {
-    atTime = ((realToFrac nanos)/1000000000),
+    atTime = realToFrac nanos / 1000000000,
     atCycle = fromIntegral n,
     cps = bpm/60,
     paused = on == 0
     }
 
 changeTempo :: MVar Tempo -> Packet -> IO ()
-changeTempo t (Packet_Message msg) = do
+changeTempo t (Packet_Message msg) =
     case parseEspTempo (messageDatum msg) of
-      Just f -> takeMVar t >>= (\x -> putMVar t (f x))
+      Just f -> takeMVar t >>= putMVar t . f
       Nothing -> putStrLn "Warning: Unable to parse message (likely from EspGrid) as Tempo"
 changeTempo _ _ = putStrLn "Serious error: Can only process Packet_Message"
 
@@ -36,7 +36,7 @@
   _ <- forkIO $ forever $ do
     _ <- sendMessage socket $ Message "/esp/tempo/q" []
     response <- waitAddress socket "/esp/tempo/r"
-    changeTempo t response
+    Sound.Tidal.EspGrid.changeTempo t response
     threadDelay 200000
   return ()
 
diff --git a/src/Sound/Tidal/MiniTidal.hs b/src/Sound/Tidal/MiniTidal.hs
--- a/src/Sound/Tidal/MiniTidal.hs
+++ b/src/Sound/Tidal/MiniTidal.hs
@@ -1,21 +1,19 @@
-{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleInstances, TemplateHaskell #-}
 
 module Sound.Tidal.MiniTidal (miniTidal,miniTidalIO,main) where
 
-import           Data.Functor.Identity (Identity)
-import           Text.Parsec.Language (haskellDef)
-import           Text.Parsec.Prim (ParsecT,parserZero)
+import           Text.Parsec.Prim (parserZero)
 import           Text.ParserCombinators.Parsec
-import qualified Text.ParserCombinators.Parsec.Token as P
 import           Control.Monad (forever)
-import Control.Applicative (liftA2)
--- import Data.List (intercalate)
--- import Data.Bool (bool)
--- import Data.Ratio
+import           Control.Applicative (liftA2)
+-- import           Language.Haskell.TH
 
 import           Sound.Tidal.Context (Pattern,ControlMap,ControlPattern,Enumerable,Parseable,Time,Arc,TPat,Stream)
 import qualified Sound.Tidal.Context as T
+import           Sound.Tidal.MiniTidal.Token
+import           Sound.Tidal.MiniTidal.TH
 
+
 -- This is depended upon by Estuary, and changes to its type will cause problems downstream for Estuary.
 miniTidal :: String -> Either ParseError (Pattern ControlMap)
 miniTidal = parse miniTidalParser "miniTidal"
@@ -86,12 +84,8 @@
 listTransformationArg :: MiniTidal a => Parser [Pattern a -> Pattern a]
 listTransformationArg = try $ parensOrNot $ brackets (commaSep transformation)
 
---  d1 $ spread ($) [density 2, rev, slow 2, striate 3, (# speed "0.8")] $ sound "[bd*2 [~ bd]] [sn future]*2 cp jvbass*4"
---  spread  ((a -> b) -> a -> b) -> [ControlPattern -> ControlPattern] -> ControlPattern -> ControlPattern
-
-
 silence :: Parser (Pattern a)
-silence = function "silence" >> return T.silence
+silence = $(function "silence")
 
 instance MiniTidal ControlMap where
   literal = parserZero
@@ -104,65 +98,66 @@
 
 controlPatternMergeOperator :: Parser (ControlPattern -> ControlPattern -> ControlPattern)
 controlPatternMergeOperator = choice [
-  op "#" >> return (T.#),
-  op "|>" >> return (T.|>),
-  op "<|" >> return (T.<|),
-  op "|>|" >> return (T.|>|),
-  op "|<|" >> return (T.|<),
-  op "|+|" >> return (T.|+|),
-  op "|-|" >> return (T.|-|),
-  op "|*|" >> return (T.|*|),
-  op "|/|" >> return (T.|/|)
+  $(op "#"),
+  $(op "|>"),
+  $(op "<|"),
+  $(op "|>"),
+  $(op "|<|"),
+  $(op "|+|"),
+  $(op "|-|"),
+  $(op "|*|"),
+  $(op "|/|")
   ]
 
 specificControlPatterns :: Parser ControlPattern
 specificControlPatterns = choice [
   try $ parens specificControlPatterns,
-  (function "coarse" >> return T.coarse) <*> patternArg,
-  (function "cut" >> return T.cut) <*> patternArg,
-  (function "n" >> return T.n) <*> patternArg,
-  (function "up" >> return T.up) <*> patternArg,
-  (function "speed" >> return T.speed) <*> patternArg,
-  (function "pan" >> return T.pan) <*> patternArg,
-  (function "shape" >> return T.shape) <*> patternArg,
-  (function "gain" >> return T.gain) <*> patternArg,
-  (function "accelerate" >> return T.accelerate) <*> patternArg,
-  (function "bandf" >> return T.bandf) <*> patternArg,
-  (function "bandq" >> return T.bandq) <*> patternArg,
-  (function "begin" >> return T.begin) <*> patternArg,
-  (function "crush" >> return T.crush) <*> patternArg,
-  (function "cutoff" >> return T.cutoff) <*> patternArg,
-  (function "delayfeedback" >> return T.delayfeedback) <*> patternArg,
-  (function "delaytime" >> return T.delaytime) <*> patternArg,
-  (function "delay" >> return T.delay) <*> patternArg,
-  (function "end" >> return T.end) <*> patternArg,
-  (function "hcutoff" >> return T.hcutoff) <*> patternArg,
-  (function "hresonance" >> return T.hresonance) <*> patternArg,
-  (function "resonance" >> return T.resonance) <*> patternArg,
-  (function "shape" >> return T.shape) <*> patternArg,
-  (function "loop" >> return T.loop) <*> patternArg,
-  (function "s" >> return T.s) <*> patternArg,
-  (function "sound" >> return T.sound) <*> patternArg,
-  (function "vowel" >> return T.vowel) <*> patternArg,
-  (function "unit" >> return T.unit) <*> patternArg,
-  (function "note" >> return T.note) <*> patternArg
+  $(function "coarse") <*> patternArg,
+  $(function "cut") <*> patternArg,
+  $(function "n") <*> patternArg,
+  $(function "up") <*> patternArg,
+  $(function "speed") <*> patternArg,
+  $(function "pan") <*> patternArg,
+  $(function "shape") <*> patternArg,
+  $(function "gain") <*> patternArg,
+  $(function "accelerate") <*> patternArg,
+  $(function "bandf") <*> patternArg,
+  $(function "bandq") <*> patternArg,
+  $(function "begin") <*> patternArg,
+  $(function "crush") <*> patternArg,
+  $(function "cutoff") <*> patternArg,
+  $(function "delayfeedback") <*> patternArg,
+  $(function "delaytime") <*> patternArg,
+  $(function "delay") <*> patternArg,
+  $(function "end") <*> patternArg,
+  $(function "hcutoff") <*> patternArg,
+  $(function "hresonance") <*> patternArg,
+  $(function "resonance") <*> patternArg,
+  $(function "shape") <*> patternArg,
+  $(function "loop") <*> patternArg,
+  $(function "s") <*> patternArg,
+  $(function "sound") <*> patternArg,
+  $(function "vowel") <*> patternArg,
+  $(function "unit") <*> patternArg,
+  $(function "note") <*> patternArg
   ]
 
 genericComplexPattern :: MiniTidal a => Parser (Pattern a)
 genericComplexPattern = choice [
   try $ parens genericComplexPattern,
   lp_p <*> listPatternArg,
-  l_p <*> listLiteralArg
+  l_p <*> listLiteralArg,
+  pInt_p <*> patternArg
   ]
 
 p_p_noArgs :: Parser (Pattern a -> Pattern a)
 p_p_noArgs  = choice [
-  function "brak" >> return T.brak,
-  function "rev" >> return T.rev,
-  function "palindrome" >> return T.palindrome,
-  function "stretch" >> return T.stretch,
-  function "loopFirst" >> return T.loopFirst,
-  function "degrade" >> return T.degrade
+  $(function "brak"),
+  $(function "rev"),
+  $(function "palindrome"),
+  $(function "stretch"),
+  $(function "loopFirst"),
+  $(function "degrade")
   ]
 
 p_p :: (MiniTidal a, MiniTidal a) => Parser (Pattern a -> Pattern a)
@@ -184,6 +179,7 @@
   lTime_p_p <*> listLiteralArg
   ]
 
+lt_p_p :: MiniTidal a => Parser ([t -> Pattern a] -> t -> Pattern a)
 lt_p_p = choice [
   try $ parens lt_p_p,
   spreads <*> (nestedParens $ reservedOp "$" >> return ($))
@@ -191,18 +187,18 @@
 
 l_p :: MiniTidal a => Parser ([a] -> Pattern a)
 l_p = choice [
-  function "listToPat" >> return T.listToPat,
-  function "choose" >> return T.choose,
-  function "cycleChoose" >> return T.cycleChoose
+  $(function "listToPat"),
+  $(function "choose"),
+  $(function "cycleChoose")
   ]
 
 lp_p :: MiniTidal a => Parser ([Pattern a] -> Pattern a)
 lp_p = choice [
-  function "stack" >> return T.stack,
-  function "fastcat" >> return T.fastcat,
-  function "slowcat" >> return T.slowcat,
-  function "cat" >> return T.cat,
-  function "randcat" >> return T.randcat
+  $(function "stack"),
+  $(function "fastcat"),
+  $(function "slowcat"),
+  $(function "cat"),
+  $(function "randcat")
   ]
 
 pInt_p :: MiniTidal a => Parser (Pattern Int -> Pattern a)
@@ -215,102 +211,110 @@
 p_p_p = choice [
   try $ parens p_p_p,
   liftA2 <$> binaryFunctions,
-  function "overlay" >> return T.overlay,
-  function "append" >> return T.append,
+  $(function "overlay"),
+  $(function "append"),
   vTime_p_p_p <*> literalArg,
   pInt_p_p_p <*> patternArg
   ]
 
+pTime_p_p :: MiniTidal a => Parser (Pattern Time -> Pattern a -> Pattern a)
 pTime_p_p = choice [
   try $ parens pTime_p_p,
-  function "fast" >> return T.fast,
-  function "fastGap" >> return T.fastGap,
-  function "density" >> return T.density,
-  function "slow" >> return T.slow,
-  function "trunc" >> return T.trunc,
-  function "fastGap" >> return T.fastGap,
-  function "densityGap" >> return T.densityGap,
-  function "sparsity" >> return T.sparsity,
-  function "trunc" >> return T.trunc,
-  function "linger" >> return T.linger,
-  function "segment" >> return T.segment,
-  function "discretise" >> return T.discretise,
-  function "timeLoop" >> return T.timeLoop,
-  function "swing" >> return T.swing,
+  $(function "fast"),
+  $(function "fastGap"),
+  $(function "density"),
+  $(function "slow"),
+  $(function "trunc"),
+  $(function "fastGap"),
+  $(function "densityGap"),
+  $(function "sparsity"),
+  $(function "trunc"),
+  $(function "linger"),
+  $(function "segment"),
+  $(function "discretise"),
+  $(function "timeLoop"),
+  $(function "swing"),
   pTime_pTime_p_p <*> patternArg
   ]
 
+lTime_p_p :: MiniTidal a => Parser ([Time] -> Pattern a -> Pattern a)
 lTime_p_p = choice [
   try $ parens lTime_p_p,
+  $(function "spaceOut"),
   spreads <*> parens vTime_p_p -- re: spread
   ]
 
+spreads :: MiniTidal a => Parser ((b -> t -> Pattern a) -> [b] -> t -> Pattern a)
 spreads = choice [
-  function "spread" >> return T.spread,
-  function "slowspread" >> return T.slowspread,
-  function "fastspread" >> return T.fastspread
+  $(function "spread"),
+  $(function "slowspread"),
+  $(function "fastspread")
   ]
 
+pInt_p_p :: MiniTidal a => Parser (Pattern Int -> Pattern a -> Pattern a)
 pInt_p_p = choice [
   try $ parens pInt_p_p,
-  function "iter" >> return T.iter,
-  function "iter'" >> return T.iter',
-  function "ply" >> return T.ply,
-  function "substruct'" >> return T.substruct',
-  function "slowstripe" >> return T.slowstripe,
+  $(function "iter"),
+  $(function "iter'"),
+  $(function "ply"),
+  $(function "substruct'"),
+  $(function "slowstripe"),
+  $(function "shuffle"),
+  $(function "scramble"),
   pInt_pInt_p_p <*> patternArg
   ]
 
-pString_p_p = function "substruct" >> return T.substruct
+pString_p_p :: MiniTidal a => Parser (Pattern String -> Pattern a -> Pattern a)
+pString_p_p = $(function "substruct")
 
+pDouble_p_p :: MiniTidal a => Parser (Pattern Double -> Pattern a -> Pattern a)
 pDouble_p_p = choice [
   try $ parens pDouble_p_p,
-  function "degradeBy" >> return T.degradeBy,
-  function "unDegradeBy" >> return T.unDegradeBy,
+  $(function "degradeBy"),
+  $(function "unDegradeBy"),
   vInt_pDouble_p_p <*> literalArg
   ]
 
+vTime_p_p :: MiniTidal a => Parser (Time -> Pattern a -> Pattern a)
 vTime_p_p = choice [
   try $ parens vTime_p_p,
-  function "rotL" >> return T.rotL,
-  function "rotR" >> return T.rotR,
+  $(function "rotL"),
+  $(function "rotR"),
   vTime_vTime_p_p <*> literalArg
   ]
 
-vInt_p_p = choice [
-  function "shuffle" >> return T.shuffle,
-  function "scramble" >> return T.scramble,
-  function "repeatCycles" >> return T.repeatCycles
-  ]
+vInt_p_p :: MiniTidal a => Parser (Int -> Pattern a -> Pattern a)
+vInt_p_p = $(function "repeatCycles")
 
+vTimeTime_p_p :: MiniTidal a => Parser ((Time,Time) -> Pattern a -> Pattern a)
 vTimeTime_p_p = choice [
-  function "compress" >> return T.compressArc,
-  function "zoom" >> return T.zoomArc,
-  function "compressTo" >> return T.compressArcTo
+  $(function "compress"),
+  $(function "zoom"),
+  $(function "compressTo")
   ]
 
+t_p_p :: MiniTidal a => Parser ((Pattern a -> Pattern a) -> Pattern a -> Pattern a)
 t_p_p = choice [
   try $ parens t_p_p,
-  function "sometimes" >> return T.sometimes,
-  function "often" >> return T.often,
-  function "rarely" >> return T.rarely,
-  function "almostNever" >> return T.almostNever,
-  function "almostAlways" >> return T.almostAlways,
-  function "never" >> return T.never,
-  function "always" >> return T.always,
-  function "superimpose" >> return T.superimpose,
-  function "someCycles" >> return T.someCycles,
-  function "somecycles" >> return T.somecycles,
+  $(function "sometimes"),
+  $(function "often"),
+  $(function "rarely"),
+  $(function "almostNever"),
+  $(function "almostAlways"),
+  $(function "never"),
+  $(function "always"),
+  $(function "superimpose"),
+  $(function "someCycles"),
   pInt_t_p_p <*> patternArg,
   pDouble_t_p_p <*> patternArg,
   lvInt_t_p_p <*> listLiteralArg,
   vInt_t_p_p <*> literalArg,
-  vDouble_t_p_p <*> literalArg
+  vDouble_t_p_p <*> literalArg,
+  vTimeTime_t_p_p <*> literalArg
   ]
 
-lvTime_p_p = function "spaceOut" >> return T.spaceOut
-
-lpInt_p_p = function "distrib" >> return T.distrib
+lpInt_p_p :: MiniTidal a => Parser ([Pattern Int] -> Pattern a -> Pattern a)
+lpInt_p_p = $(function "distrib")
 
 lp_p_p :: MiniTidal a => Parser ([Pattern a] -> Pattern a -> Pattern a)
 lp_p_p = choice [
@@ -318,69 +322,86 @@
   try $ spreads <*> parens p_p_p
   ]
 
+l_pInt_p :: MiniTidal a => Parser ([a] -> Pattern Int -> Pattern a)
 l_pInt_p = choice [
   try $ parens l_pInt_p,
   vInt_l_pInt_p <*> literalArg
   ]
 
-vInt_l_pInt_p = function "fit" >> return T.fit
+vInt_l_pInt_p :: MiniTidal a => Parser (Int -> [a] -> Pattern Int -> Pattern a)
+vInt_l_pInt_p = $(function "fit")
 
-vTime_p_p_p = function "wedge" >> return T.wedge
+vTime_p_p_p :: MiniTidal a => Parser (Time -> Pattern a -> Pattern a -> Pattern a)
+vTime_p_p_p = $(function "wedge")
 
-vInt_pDouble_p_p = function "degradeOverBy" >> return T.degradeOverBy
+vInt_pDouble_p_p :: MiniTidal a => Parser (Int -> Pattern Double -> Pattern a -> Pattern a)
+vInt_pDouble_p_p = $(function "degradeOverBy")
 
+pInt_t_p_p :: MiniTidal a => Parser (Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
 pInt_t_p_p = choice [
   try $ parens pInt_t_p_p,
-  function "every" >> return T.every,
+  $(function "every"),
   pInt_pInt_t_p_p <*> patternArg
   ]
 
-pDouble_t_p_p = function "sometimesBy" >> return T.sometimesBy
+pDouble_t_p_p :: MiniTidal a => Parser (Pattern Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+pDouble_t_p_p = $(function "sometimesBy")
 
-lvInt_t_p_p = function "foldEvery" >> return T.foldEvery
+lvInt_t_p_p :: MiniTidal a => Parser ([Int] -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+lvInt_t_p_p = $(function "foldEvery")
 
-vTime_vTime_p_p = function "playFor" >> return T.playFor
+vTime_vTime_p_p :: MiniTidal a => Parser (Time -> Time -> Pattern a -> Pattern a)
+vTime_vTime_p_p = $(function "playFor")
 
-vTimeTime_t_p_p = function "within" >> return T.withinArc
+vTimeTime_t_p_p :: MiniTidal a => Parser ((Time,Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+vTimeTime_t_p_p = $(function "within")
 
+vInt_t_p_p :: MiniTidal a => Parser (Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
 vInt_t_p_p = choice [
   try $ parens vInt_t_p_p,
-  function "chunk" >> return T.chunk,
+  $(function "chunk"),
   vInt_vInt_t_p_p <*> literalArg
   ]
 
-vDouble_t_p_p = choice [
-  function "someCyclesBy" >> return T.someCyclesBy,
-  function "somecyclesBy" >> return T.somecyclesBy
-  ]
+vDouble_t_p_p :: MiniTidal a => Parser (Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+vDouble_t_p_p = $(function "someCyclesBy")
 
+pInt_pInt_p_p :: MiniTidal a => Parser (Pattern Int -> Pattern Int -> Pattern a -> Pattern a)
 pInt_pInt_p_p = choice [
   try $ parens pInt_pInt_p_p,
-  function "euclid" >> return T.euclid,
-  function "euclidInv" >> return T.euclidInv,
+  $(function "euclid"),
+  $(function "euclidInv"),
   vInt_pInt_pInt_p_p <*> literalArg
   ]
 
-pTime_pTime_p_p = function "swingBy" >> return T.swingBy
+pTime_pTime_p_p :: MiniTidal a => Parser (Pattern Time -> Pattern Time -> Pattern a -> Pattern a)
+pTime_pTime_p_p = $(function "swingBy")
 
-pInt_pInt_t_p_p = function "every'" >> return T.every'
+pInt_pInt_t_p_p :: MiniTidal a => Parser (Pattern Int -> Pattern Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+pInt_pInt_t_p_p = $(function "every'")
 
-vInt_vInt_t_p_p = function "whenmod" >> return T.whenmod
+vInt_vInt_t_p_p :: MiniTidal a => Parser (Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a)
+vInt_vInt_t_p_p = $(function "whenmod")
 
+pInt_p_p_p :: MiniTidal a => Parser (Pattern Int -> Pattern a -> Pattern a -> Pattern a)
 pInt_p_p_p = choice [
   try $ parens pInt_p_p_p,
   pInt_pInt_p_p_p <*> patternArg
   ]
 
-pInt_pInt_p_p_p = function "euclidFull" >> return T.euclidFull
+pInt_pInt_p_p_p :: MiniTidal a => Parser (Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a)
+pInt_pInt_p_p_p = $(function "euclidFull")
 
+vInt_pInt_pInt_p_p :: MiniTidal a => Parser (Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a)
 vInt_pInt_pInt_p_p = choice [
   try $ parens vInt_pInt_pInt_p_p,
   pTime_vInt_pInt_pInt_p_p <*> patternArg
   ]
 
-pTime_vInt_pInt_pInt_p_p = function "fit'" >> return T.fit'
+pTime_vInt_pInt_pInt_p_p :: MiniTidal a => Parser (Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a)
+pTime_vInt_pInt_pInt_p_p = $(function "fit'")
 
+pControl_pControl :: Parser (ControlPattern -> ControlPattern)
 pControl_pControl = choice [
   try $ parens pControl_pControl,
   pInt_pControl_pControl <*> patternArg,
@@ -389,41 +410,48 @@
   tControl_pControl_pControl <*> transformationArg
   ]
 
-tControl_pControl_pControl = function "jux" >> return T.jux
+tControl_pControl_pControl :: Parser ((ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern)
+tControl_pControl_pControl = $(function "jux")
 
+pInt_pControl_pControl :: Parser (Pattern Int -> ControlPattern -> ControlPattern)
 pInt_pControl_pControl = choice [
-  function "chop" >> return T.chop,
-  function "striate" >> return T.striate
+  $(function "chop"),
+  $(function "striate")
   ]
 
+pDouble_pControl_pControl :: Parser (Pattern Double -> ControlPattern -> ControlPattern)
 pDouble_pControl_pControl = choice [
   try $ parens pDouble_pControl_pControl,
   pInt_pDouble_pControl_pControl <*> patternArg
   ]
 
-pInt_pDouble_pControl_pControl = function "striate'" >> return T.striate'
+pInt_pDouble_pControl_pControl :: Parser (Pattern Int -> Pattern Double -> ControlPattern -> ControlPattern)
+pInt_pDouble_pControl_pControl = $(function "striate'")
 
+pTime_pControl_pControl :: Parser (Pattern Time -> ControlPattern -> ControlPattern)
 pTime_pControl_pControl = choice [
   try $ parens pTime_pControl_pControl,
   pDouble_pTime_pControl_pControl <*> patternArg
   ]
 
+pDouble_pTime_pControl_pControl :: Parser (Pattern Double -> Pattern Time -> ControlPattern -> ControlPattern)
 pDouble_pTime_pControl_pControl = choice [
   try $ parens pDouble_pTime_pControl_pControl,
   pInteger_pDouble_pTime_pControl_pControl <*> patternArg
   ]
 
-pInteger_pDouble_pTime_pControl_pControl = function "stut" >> return T.stut
+pInteger_pDouble_pTime_pControl_pControl :: Parser (Pattern Integer -> Pattern Double -> Pattern Time -> ControlPattern -> ControlPattern)
+pInteger_pDouble_pTime_pControl_pControl = $(function "stut")
 
 simpleDoublePatterns :: Parser (Pattern Double)
 simpleDoublePatterns = choice [
-  function "rand" >> return T.rand,
-  function "sine" >> return T.sine,
-  function "saw" >> return T.saw,
-  function "isaw" >> return T.isaw,
-  function "tri" >> return T.tri,
-  function "square" >> return T.square,
-  function "cosine" >> return T.cosine
+  $(function "rand"),
+  $(function "sine"),
+  $(function "saw"),
+  $(function "isaw"),
+  $(function "tri"),
+  $(function "square"),
+  $(function "cosine")
   ]
 
 binaryNumFunctions :: Num a => Parser (a -> a -> a)
@@ -481,6 +509,17 @@
   mergeOperator = parserZero
   binaryFunctions = parserZero
 
+instance MiniTidal (Time,Time) where
+  literal = do
+    xs <- parens (commaSep1 literal)
+    if length xs == 2 then return ((xs!!0),(xs!!1)) else unexpected "(Time,Time) must contain exactly two values"
+  simplePattern = pure <$> literal
+  transformationWithArguments = p_p_noArgs
+  transformationWithoutArguments = p_p
+  complexPattern = atom <*> literal
+  mergeOperator = parserZero
+  binaryFunctions = parserZero
+
 instance MiniTidal String where
   literal = stringLiteral
   simplePattern = parseBP'
@@ -491,150 +530,35 @@
   binaryFunctions = parserZero
 
 fractionalMergeOperator :: Fractional a => Parser (Pattern a -> Pattern a -> Pattern a)
-fractionalMergeOperator = op "/" >> return (/)
+fractionalMergeOperator = opParser "/" >> return (/)
 
 numMergeOperator :: Num a => Parser (Pattern a -> Pattern a -> Pattern a)
 numMergeOperator = choice [
-  op "+" >> return (+),
-  op "-" >> return (-),
-  op "*" >> return (*)
+  opParser "+" >> return (+),
+  opParser "-" >> return (-),
+  opParser "*" >> return (*)
   ]
 
 enumComplexPatterns :: (Enum a, Num a, MiniTidal a) => Parser (Pattern a)
 enumComplexPatterns = choice [
-  (function "run" >> return T.run) <*> patternArg,
-  (function "scan" >> return T.scan) <*> patternArg
+  $(function "run") <*> patternArg,
+  $(function "scan") <*> patternArg
   ]
 
 numComplexPatterns :: (Num a, MiniTidal a) => Parser (Pattern a)
 numComplexPatterns = choice [
-  (function "irand" >> return T.irand) <*> literal,
-  (function "toScale'" >> return T.toScale') <*> literalArg <*> listLiteralArg <*> patternArg,
-  (function "toScale" >> return T.toScale) <*> listLiteralArg <*> patternArg
+  $(function "irand") <*> literal,
+  $(function "toScale'") <*> literalArg <*> listLiteralArg <*> patternArg,
+  $(function "toScale") <*> listLiteralArg <*> patternArg
   ]
 
 intComplexPatterns :: Parser (Pattern Int)
 intComplexPatterns = choice [
-  (function "randStruct" >> return T.randStruct) <*> literalArg
+  $(function "randStruct") <*> literalArg
   ]
 
 atom :: Applicative m => Parser (a -> m a)
-atom = (function "pure" <|> function "atom" <|> function "return") >> return (pure)
-
-double :: Parser Double
-double = choice [
-  parens $ symbol "-" >> float >>= return . (* (-1)),
-  parens double,
-  try float,
-  try $ fromIntegral <$> integer
-  ]
-
-int :: Parser Int
-int = try $ parensOrNot $ fromIntegral <$> integer
-
-function :: String -> Parser ()
-function x = reserved x <|> try (parens (function x))
-
-op :: String -> Parser ()
-op x = reservedOp x <|> try (parens (op x))
-
-parensOrNot :: Parser a -> Parser a
-parensOrNot p = p <|> try (parens (parensOrNot p))
-
-nestedParens :: Parser a -> Parser a
-nestedParens p = try (parens p) <|> try (parens (nestedParens p))
-
-applied :: Parser a -> Parser a
-applied p = op "$" >> p
-
-appliedOrNot :: Parser a -> Parser a
-appliedOrNot p = applied p <|> p
-
-parensOrApplied :: Parser a -> Parser a
-parensOrApplied p = try (parens p) <|> try (applied p)
-
-tokenParser :: P.TokenParser a
-tokenParser = P.makeTokenParser $ haskellDef {
-  P.reservedNames = ["chop","striate","striate'","stut","jux","brak","rev",
-    "palindrome","fast","density","slow","iter","iter'","trunc","swingBy","every","whenmod",
-    "append","append'","silence","s","sound","n","up","speed","vowel","pan","shape","gain",
-    "accelerate","bandf","bandq","begin","coarse","crush","cut","cutoff","delayfeedback",
-    "delaytime","delay","end","hcutoff","hresonance","loop","resonance","shape","unit",
-    "sine","saw","isaw","fit","irand","tri","square","rand",
-    "pure","return","stack","fastcat","slowcat","cat","atom","overlay","run","scan","fast'",
-    "fastGap","densityGap","sparsity","rotL","rotR","playFor","every'","foldEvery",
-    "cosine","superimpose","trunc","linger","zoom","compress","sliceArc","within","within'",
-    "revArc","euclid","euclidFull","euclidInv","distrib","wedge","prr","preplace","prep","preplace1",
-    "protate","prot","prot1","discretise","segment","struct","substruct","compressTo",
-    "substruct'","stripe","slowstripe","stretch","fit'","chunk","loopFirst","timeLoop","swing",
-    "choose","degradeBy","unDegradeBy","degradeOverBy","sometimesBy","sometimes","often",
-    "rarely","almostNever","almostAlways","never","always","someCyclesBy","somecyclesBy",
-    "someCycles","somecycles","substruct'","repeatCycles","spaceOut","fill","ply","shuffle",
-    "scramble","breakUp","degrade","randcat","randStruct","toScale'","toScale","cycleChoose",
-    "d1","d2","d3","d4","d5","d6","d7","d8","d9","t1","t2","t3","t4","t5","t6","t7","t8","t9",
-    "cps","xfadeIn","note","spread","slowspread","fastspread"],
-  P.reservedOpNames = ["+","-","*","/","<~","~>","#","|+|","|-|","|*|","|/|","$","\"","|>","<|","|>|","|<|"]
-  }
-
-{- Not currently in use
-angles :: ParsecT String u Identity a -> ParsecT String u Identity a
-angles = P.angles tokenParser
-braces :: ParsecT String u Identity a -> ParsecT String u Identity a
-braces = P.braces tokenParser
-charLiteral :: ParsecT String u Identity Char
-charLiteral = P.charLiteral tokenParser
-colon :: ParsecT String u Identity String
-colon = P.colon tokenParser
-comma :: ParsecT String u Identity String
-comma = P.comma tokenParser
-decimal :: ParsecT String u Identity Integer
-decimal = P.decimal tokenParser
-dot :: ParsecT String u Identity String
-dot = P.dot tokenParser
-hexadecimal :: ParsecT String u Identity Integer
-hexadecimal = P.hexadecimal tokenParser
-identifier :: ParsecT String u Identity String
-identifier = P.identifier tokenParser
-lexeme :: ParsecT String u Identity a -> ParsecT String u Identity a
-lexeme = P.lexeme tokenParser
-naturalOrFloat :: ParsecT String u Identity (Either Integer Double)
-naturalOrFloat = P.naturalOrFloat tokenParser
-natural :: ParsecT String u Identity Integer
-natural = P.natural tokenParser
-octal :: ParsecT String u Identity Integer
-octal = P.octal tokenParser
-operator :: ParsecT String u Identity String
-operator = P.operator tokenParser
-semi :: ParsecT String u Identity String
-semi = P.semi tokenParser
-semiSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]
-semiSep1 = P.semiSep1 tokenParser
-semiSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]
-semiSep = P.semiSep tokenParser
--}
-
-brackets :: ParsecT String u Identity a -> ParsecT String u Identity a
-brackets = P.brackets tokenParser
-commaSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]
-commaSep1 = P.commaSep1 tokenParser
-commaSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]
-commaSep = P.commaSep tokenParser
-float :: ParsecT String u Identity Double
-float = P.float tokenParser
-integer :: ParsecT String u Identity Integer
-integer = P.integer tokenParser
-parens :: ParsecT String u Identity a -> ParsecT String u Identity a
-parens = P.parens tokenParser
-reservedOp :: String -> ParsecT String u Identity ()
-reservedOp = P.reservedOp tokenParser
-reserved :: String -> ParsecT String u Identity ()
-reserved = P.reserved tokenParser
-stringLiteral :: ParsecT String u Identity String
-stringLiteral = P.stringLiteral tokenParser
-symbol :: String -> ParsecT String u Identity String
-symbol = P.symbol tokenParser
-whiteSpace :: ParsecT String u Identity ()
-whiteSpace = P.whiteSpace tokenParser
+atom = (functionParser "pure" <|> functionParser "atom" <|> functionParser "return") >> return (pure)
 
 parseBP' :: (Enumerable a, Parseable a) => Parser (Pattern a)
 parseBP' = parseTPat' >>= return . T.toPat
diff --git a/src/Sound/Tidal/MiniTidal/TH.hs b/src/Sound/Tidal/MiniTidal/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Tidal/MiniTidal/TH.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Sound.Tidal.MiniTidal.TH where
+
+import Language.Haskell.TH
+import Sound.Tidal.MiniTidal.Token
+
+op :: String -> Q Exp
+op x = do -- op "x" >> return T.x
+  let y = appE [|opParser|] $ return (LitE $ StringL x)
+  let z = appE [|return|] $ return (VarE $ mkName $ "T." ++ x)
+  uInfixE y [|(>>)|] z
+
+function :: String -> Q Exp
+function x = do -- function "x" >> return T.x
+  let y = appE [|functionParser|] $ return (LitE $ StringL x)
+  let z = appE [|return|] $ return (VarE $ mkName $ "T." ++ x)
+  uInfixE y [|(>>)|] z
diff --git a/src/Sound/Tidal/MiniTidal/Token.hs b/src/Sound/Tidal/MiniTidal/Token.hs
new file mode 100644
--- /dev/null
+++ b/src/Sound/Tidal/MiniTidal/Token.hs
@@ -0,0 +1,122 @@
+module Sound.Tidal.MiniTidal.Token where
+
+import           Data.Functor.Identity (Identity)
+import           Text.Parsec.Prim (ParsecT,parserZero)
+import           Text.ParserCombinators.Parsec
+import           Text.Parsec.Language (haskellDef)
+import qualified Text.ParserCombinators.Parsec.Token as P
+
+tokenParser :: P.TokenParser a
+tokenParser = P.makeTokenParser $ haskellDef {
+  P.reservedNames = ["chop","striate","striate'","stut","jux","brak","rev",
+    "palindrome","fast","density","slow","iter","iter'","trunc","swingBy","every","whenmod",
+    "append","append'","silence","s","sound","n","up","speed","vowel","pan","shape","gain",
+    "accelerate","bandf","bandq","begin","coarse","crush","cut","cutoff","delayfeedback",
+    "delaytime","delay","end","hcutoff","hresonance","loop","resonance","shape","unit",
+    "sine","saw","isaw","fit","irand","tri","square","rand",
+    "pure","return","stack","fastcat","slowcat","cat","atom","overlay","run","scan","fast'",
+    "fastGap","densityGap","sparsity","rotL","rotR","playFor","every'","foldEvery",
+    "cosine","superimpose","trunc","linger","zoom","compress","sliceArc","within","within'",
+    "revArc","euclid","euclidFull","euclidInv","distrib","wedge","prr","preplace","prep","preplace1",
+    "protate","prot","prot1","discretise","segment","struct","substruct","compressTo",
+    "substruct'","stripe","slowstripe","stretch","fit'","chunk","loopFirst","timeLoop","swing",
+    "choose","degradeBy","unDegradeBy","degradeOverBy","sometimesBy","sometimes","often",
+    "rarely","almostNever","almostAlways","never","always","someCyclesBy","somecyclesBy",
+    "someCycles","somecycles","substruct'","repeatCycles","spaceOut","fill","ply","shuffle",
+    "scramble","breakUp","degrade","randcat","randStruct","toScale'","toScale","cycleChoose",
+    "d1","d2","d3","d4","d5","d6","d7","d8","d9","t1","t2","t3","t4","t5","t6","t7","t8","t9",
+    "cps","xfadeIn","note","spread","slowspread","fastspread"],
+  P.reservedOpNames = ["+","-","*","/","<~","~>","#","|+|","|-|","|*|","|/|","$","\"","|>","<|","|>|","|<|"]
+  }
+
+{- Not currently in use
+angles :: ParsecT String u Identity a -> ParsecT String u Identity a
+angles = P.angles tokenParser
+braces :: ParsecT String u Identity a -> ParsecT String u Identity a
+braces = P.braces tokenParser
+charLiteral :: ParsecT String u Identity Char
+charLiteral = P.charLiteral tokenParser
+colon :: ParsecT String u Identity String
+colon = P.colon tokenParser
+comma :: ParsecT String u Identity String
+comma = P.comma tokenParser
+decimal :: ParsecT String u Identity Integer
+decimal = P.decimal tokenParser
+dot :: ParsecT String u Identity String
+dot = P.dot tokenParser
+hexadecimal :: ParsecT String u Identity Integer
+hexadecimal = P.hexadecimal tokenParser
+identifier :: ParsecT String u Identity String
+identifier = P.identifier tokenParser
+lexeme :: ParsecT String u Identity a -> ParsecT String u Identity a
+lexeme = P.lexeme tokenParser
+naturalOrFloat :: ParsecT String u Identity (Either Integer Double)
+naturalOrFloat = P.naturalOrFloat tokenParser
+natural :: ParsecT String u Identity Integer
+natural = P.natural tokenParser
+octal :: ParsecT String u Identity Integer
+octal = P.octal tokenParser
+operator :: ParsecT String u Identity String
+operator = P.operator tokenParser
+semi :: ParsecT String u Identity String
+semi = P.semi tokenParser
+semiSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]
+semiSep1 = P.semiSep1 tokenParser
+semiSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]
+semiSep = P.semiSep tokenParser
+-}
+
+brackets :: ParsecT String u Identity a -> ParsecT String u Identity a
+brackets = P.brackets tokenParser
+commaSep1 :: ParsecT String u Identity a -> ParsecT String u Identity [a]
+commaSep1 = P.commaSep1 tokenParser
+commaSep :: ParsecT String u Identity a -> ParsecT String u Identity [a]
+commaSep = P.commaSep tokenParser
+float :: ParsecT String u Identity Double
+float = P.float tokenParser
+integer :: ParsecT String u Identity Integer
+integer = P.integer tokenParser
+parens :: ParsecT String u Identity a -> ParsecT String u Identity a
+parens = P.parens tokenParser
+reservedOp :: String -> ParsecT String u Identity ()
+reservedOp = P.reservedOp tokenParser
+reserved :: String -> ParsecT String u Identity ()
+reserved = P.reserved tokenParser
+stringLiteral :: ParsecT String u Identity String
+stringLiteral = P.stringLiteral tokenParser
+symbol :: String -> ParsecT String u Identity String
+symbol = P.symbol tokenParser
+whiteSpace :: ParsecT String u Identity ()
+whiteSpace = P.whiteSpace tokenParser
+
+functionParser :: String -> Parser ()
+functionParser x = reserved x <|> try (parens (functionParser x))
+
+opParser :: String -> Parser ()
+opParser x = reservedOp x <|> try (parens (opParser x))
+
+double :: Parser Double
+double = choice [
+  parens $ symbol "-" >> float >>= return . (* (-1)),
+  parens double,
+  try float,
+  try $ fromIntegral <$> integer
+  ]
+
+int :: Parser Int
+int = try $ parensOrNot $ fromIntegral <$> integer
+
+parensOrNot :: Parser a -> Parser a
+parensOrNot p = p <|> try (parens (parensOrNot p))
+
+nestedParens :: Parser a -> Parser a
+nestedParens p = try (parens p) <|> try (parens (nestedParens p))
+
+applied :: Parser a -> Parser a
+applied p = opParser "$" >> p
+
+appliedOrNot :: Parser a -> Parser a
+appliedOrNot p = applied p <|> p
+
+parensOrApplied :: Parser a -> Parser a
+parensOrApplied p = try (parens p) <|> try (applied p)
diff --git a/src/Sound/Tidal/Params.hs b/src/Sound/Tidal/Params.hs
--- a/src/Sound/Tidal/Params.hs
+++ b/src/Sound/Tidal/Params.hs
@@ -44,6 +44,16 @@
 pS :: String -> Pattern String -> ControlPattern
 pS name = fmap (Map.singleton name . VS)
 
+-- | patterns for internal sound routing
+toArg :: Pattern String -> ControlPattern
+toArg = pS "toArg"
+
+from :: Pattern Double -> ControlPattern
+from = pF "from"
+
+to :: Pattern Double -> ControlPattern
+to = pF "to"
+
 -- | a pattern of numbers that speed up (or slow down) samples while they play.
 accelerate :: Pattern Double -> ControlPattern
 accelerate       = pF "accelerate"
@@ -385,6 +395,55 @@
 distort :: Pattern Double -> ControlPattern
 distort = pF "distort"
 
+-- Spectral freeze
+freeze :: Pattern Double -> ControlPattern
+freeze = pF "freeze"
+
+-- Spectral delay
+xsdelay :: Pattern Double -> ControlPattern
+xsdelay = pF "xsdelay"
+
+tsdelay :: Pattern Double -> ControlPattern
+tsdelay = pF "tsdelay"
+
+-- Spectral conform
+real :: Pattern Double -> ControlPattern
+real = pF "real"
+
+imag :: Pattern Double -> ControlPattern
+imag = pF "imag"
+
+-- Spectral enhance
+enhance :: Pattern Double -> ControlPattern
+enhance = pF "enhance"
+
+partials :: Pattern Double -> ControlPattern
+partials = pF "partials"
+
+-- Spectral comb
+comb :: Pattern Double -> ControlPattern
+comb = pF "comb"
+
+-- Spectral smear
+smear :: Pattern Double -> ControlPattern
+smear = pF "smear"
+
+-- Spectral scramble
+scram :: Pattern Double -> ControlPattern
+scram = pF "scram"
+
+-- Spectral binshift
+binshift :: Pattern Double -> ControlPattern
+binshift = pF "binshift"
+
+-- High pass sort of spectral filter
+hbrick :: Pattern Double -> ControlPattern
+hbrick = pF "hbrick"
+
+-- Low pass sort of spectral filter
+lbrick :: Pattern Double -> ControlPattern
+lbrick = pF "lbrick"
+
 -- aliases
 att, bpf, bpq, chdecay, ctf, ctfg, delayfb, delayt, det, gat, hg, hpf, hpq, lag, lbd, lch, lcl, lcp, lcr, lfoc, lfoi
    , lfop, lht, llt, loh, lpf, lpq, lsn, ohdecay, phasdp, phasr, pit1, pit2, pit3, por, rel, sz, sag, scl, scp
@@ -443,10 +502,10 @@
 voi = voice
 
 midinote :: Pattern Double -> ControlPattern
-midinote = note . ((subtract 60) <$>)
+midinote = note . (subtract 60 <$>)
 
 drum :: Pattern String -> ControlPattern
-drum = n . ((subtract 60) . drumN <$>)
+drum = n . (subtract 60 . drumN <$>)
 
 drumN :: Num a => String -> a
 drumN "bd" = 36
diff --git a/src/Sound/Tidal/ParseBP.hs b/src/Sound/Tidal/ParseBP.hs
--- a/src/Sound/Tidal/ParseBP.hs
+++ b/src/Sound/Tidal/ParseBP.hs
@@ -73,15 +73,15 @@
    TPat_pE n k s thing ->
       doEuclid (toPat n) (toPat k) (toPat s) (toPat thing)
    TPat_Foot -> error "Can't happen, feet (.'s) only used internally.."
-   TPat_EnumFromTo a b -> unwrap $ fromTo <$> (toPat a) <*> (toPat b)
+   TPat_EnumFromTo a b -> unwrap $ fromTo <$> toPat a <*> toPat b
    -- TPat_EnumFromThenTo a b c -> unwrap $ fromThenTo <$> (toPat a) <*> (toPat b) <*> (toPat c)
    _ -> silence
 
 durations :: [TPat a] -> [(Int, TPat a)]
 durations [] = []
-durations ((TPat_Elongate n):xs) = (n, TPat_Silence):(durations xs)
-durations (a:(TPat_Elongate n):xs) = (n+1,a):(durations xs)
-durations (a:xs) = (1,a):(durations xs)
+durations (TPat_Elongate n : xs) = (n, TPat_Silence) : durations xs
+durations (a : TPat_Elongate n : xs) = (n+1,a) : durations xs
+durations (a:xs) = (1,a) : durations xs
 
 parseBP :: (Enumerable a, Parseable a) => String -> Either ParseError (Pattern a)
 parseBP s = toPat <$> parseTPat s
@@ -111,8 +111,8 @@
   doEuclid = euclidOff
   
 instance Enumerable Double where
-  fromTo a b = enumFromTo' a b
-  fromThenTo a b c = enumFromThenTo' a b c
+  fromTo = enumFromTo'
+  fromThenTo = enumFromThenTo'
 
 instance Parseable String where
   tPatParser = pVocable
@@ -135,24 +135,24 @@
   doEuclid = euclidOff
 
 instance Enumerable Int where
-  fromTo a b = enumFromTo' a b
-  fromThenTo a b c = enumFromThenTo' a b c
+  fromTo = enumFromTo'
+  fromThenTo = enumFromThenTo'
 
 instance Parseable Integer where
   tPatParser = pIntegral
   doEuclid = euclidOff
 
 instance Enumerable Integer where
-  fromTo a b = enumFromTo' a b
-  fromThenTo a b c = enumFromThenTo' a b c
+  fromTo = enumFromTo'
+  fromThenTo = enumFromThenTo'
 
 instance Parseable Rational where
   tPatParser = pRational
   doEuclid = euclidOff
 
 instance Enumerable Rational where
-  fromTo a b = enumFromTo' a b
-  fromThenTo a b c = enumFromThenTo' a b c
+  fromTo = enumFromTo'
+  fromThenTo = enumFromThenTo'
 
 enumFromTo' :: (Ord a, Enum a) => a -> a -> Pattern a
 enumFromTo' a b | a > b = fastFromList $ reverse $ enumFromTo b a
@@ -232,7 +232,7 @@
 -}
 
 parseRhythm :: Parseable a => Parser (TPat a) -> String -> Either ParseError (TPat a)
-parseRhythm f input = parse (pSequence f') "" input
+parseRhythm f = parse (pSequence f') ""
   where f' = f
              <|> do symbol "~" <?> "rest"
                     return TPat_Silence
@@ -253,7 +253,7 @@
                   return (length ps, ps')
 
 elongate :: [TPat a] -> TPat a
-elongate xs | any (isElongate) xs = TPat_TimeCat xs
+elongate xs | any isElongate xs = TPat_TimeCat xs
             | otherwise = TPat_Cat xs
   where isElongate (TPat_Elongate _) = True
         isElongate _ = False
@@ -270,7 +270,7 @@
 -- could use splitOn here but `TPat a` isn't a member of `EQ`..
 splitFeet :: [TPat t] -> [[TPat t]]
 splitFeet [] = []
-splitFeet pats = foot:(splitFeet pats')
+splitFeet pats = foot : splitFeet pats'
   where (foot, pats') = takeFoot pats
         takeFoot [] = ([], [])
         takeFoot (TPat_Foot:pats'') = ([], pats'')
@@ -291,7 +291,7 @@
              pts <- pStretch pt
                     <|> pReplicate pt''
              spaces
-             return $ pts
+             return pts
 
 pPolyIn :: Parseable a => Parser (TPat a) -> Parser (TPat a)
 pPolyIn f = do ps <- brackets (pSequence f `sepBy` symbol ",")
@@ -312,16 +312,15 @@
                 spaces
                 pMult $ TPat_Stack $ scale' (Just 1) ps
   where scale' _ [] = []
-        scale' base (pats@((n,_):_)) = map (\(n',pat) -> TPat_Density (TPat_Atom $ fromIntegral (fromMaybe n base)/ fromIntegral n') pat) pats
+        scale' base pats@((n,_):_) = map (\(n',pat) -> TPat_Density (TPat_Atom $ fromIntegral (fromMaybe n base)/ fromIntegral n') pat) pats
 
-pString :: Parser (String)
+pString :: Parser String
 pString = do c <- (letter <|> oneOf "0123456789") <?> "charnum"
              cs <- many (letter <|> oneOf "0123456789:.-_") <?> "string"
              return (c:cs)
 
 pVocable :: Parser (TPat String)
-pVocable = do v <- pString
-              return $ TPat_Atom v
+pVocable = TPat_Atom <$> pString
 
 pDouble :: Parser (TPat Double)
 pDouble = do f <- choice [intOrFloat, parseNote] <?> "float"
@@ -366,7 +365,7 @@
                 do char '\''
                    i <- integer <?> "chord range"
                    let chord' = take (fromIntegral i) $ concatMap (\x -> map (+ x) chord) [0,12..]
-                   return $ chord'
+                   return chord'
                   <|> return chord
 
 parseNote :: Num a => Parser a
@@ -392,7 +391,7 @@
                               ]
 
 fromNote :: Num a => Pattern String -> Pattern a
-fromNote pat = (\s -> either (const 0) id $ parse parseNote "" s) <$> pat
+fromNote pat = either (const 0) id . parse parseNote "" <$> pat
 
 pColour :: Parser (TPat ColourD)
 pColour = do name <- many1 letter <?> "colour name"
@@ -402,18 +401,16 @@
 pMult :: TPat a -> Parser (TPat a)
 pMult thing = do char '*'
                  spaces
-                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)
+                 r <- pRational <|> pPolyIn pRational <|> pPolyOut pRational
                  return $ TPat_Density r thing
               <|>
               do char '/'
                  spaces
-                 r <- (pRational <|> pPolyIn pRational  <|> pPolyOut pRational)
+                 r <- pRational <|> pPolyIn pRational <|> pPolyOut pRational
                  return $ TPat_Slow r thing
               <|>
               return thing
 
-
-
 pRand :: TPat a -> Parser (TPat a)
 pRand thing = do char '?'
                  spaces
@@ -421,7 +418,7 @@
               <|> return thing
 
 pE :: TPat a -> Parser (TPat a)
-pE thing = do (n,k,s) <- parens (pair)
+pE thing = do (n,k,s) <- parens pair
               pure $ TPat_pE n k s thing
             <|> return thing
    where pair :: Parser (TPat Int, TPat Int, TPat Int)
@@ -441,7 +438,7 @@
   do extras <- many $ do char '!'
                          -- if a number is given (without a space)slow 2 $ fast
                          -- replicate that number of times
-                         n <- ((read <$> many1 digit) <|> return (2 :: Int))
+                         n <- (read <$> many1 digit) <|> return (2 :: Int)
                          spaces
                          thing' <- pRand thing
                          -- -1 because we already have parsed the original one
@@ -451,10 +448,10 @@
 pStretch :: TPat a -> Parser [TPat a]
 pStretch thing =
   do char '@'
-     n <- ((read <$> many1 digit) <|> return 1)
+     n <- (read <$> many1 digit) <|> return 1
      return $ map (\x -> TPat_Zoom (Arc (x%n) ((x+1)%n)) thing) [0 .. (n-1)]
 
-pRatio :: Parser (Rational)
+pRatio :: Parser Rational
 pRatio = do s <- sign
             n <- natural
             result <- do char '%'
@@ -465,14 +462,13 @@
                          frac <- many1 digit
                          -- A hack, but not sure if doing this
                          -- numerically would be any faster..
-                         return (toRational $ ((read $ show n ++ "." ++ frac)  :: Double))
+                         return (toRational ((read $ show n ++ "." ++ frac)  :: Double))
                       <|>
                       return (n%1)
             return $ applySign s result
 
 pRational :: Parser (TPat Rational)
-pRational = do r <- pRatio
-               return $ TPat_Atom r
+pRational = TPat_Atom <$> pRatio
 
 {-
 pDensity :: Parser (Rational)
diff --git a/src/Sound/Tidal/Pattern.hs b/src/Sound/Tidal/Pattern.hs
--- a/src/Sound/Tidal/Pattern.hs
+++ b/src/Sound/Tidal/Pattern.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE DeriveDataTypeable, TypeSynonymInstances, FlexibleInstances #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
@@ -12,7 +11,7 @@
 import           Data.Data (Data) -- toConstr
 import           Data.List (delete, findIndex, sort, intercalate)
 import qualified Data.Map.Strict as Map
-import           Data.Maybe (isJust, fromJust, catMaybes, fromMaybe)
+import           Data.Maybe (isJust, fromJust, catMaybes, fromMaybe, mapMaybe)
 import           Data.Ratio (numerator, denominator)
 import           Data.Typeable (Typeable)
 
@@ -87,14 +86,14 @@
 
 -- | The arc of the whole cycle that the given time value falls within
 timeToCycleArc :: Time -> Arc
-timeToCycleArc t = (Arc (sam t) ((sam t) + 1))
+timeToCycleArc t = Arc (sam t) (sam t + 1)
 
 -- | A list of cycle numbers which are included in the given arc
 cyclesInArc :: Integral a => Arc -> [a]
 cyclesInArc (Arc s e)
   | s > e = []
   | s == e = [floor s]
-  | otherwise = [floor s .. (ceiling e)-1]
+  | otherwise = [floor s .. ceiling e-1]
 
 -- | A list of arcs of the whole cycles which are included in the given arc
 cycleArcsInArc :: Arc -> [Arc]
@@ -104,7 +103,7 @@
 arcCycles :: Arc -> [Arc]
 arcCycles (Arc s e) | s >= e = []
                 | sam s == sam e = [Arc s e]
-                | otherwise = (Arc s (nextSam s)) : (arcCycles (Arc (nextSam s) e))
+                | otherwise = Arc s (nextSam s) : arcCycles (Arc (nextSam s) e)
 
 -- | Like arcCycles, but returns zero-width arcs
 arcCyclesZW :: Arc -> [Arc]
@@ -114,7 +113,7 @@
 -- | Similar to 'fmap' but time is relative to the cycle (i.e. the
 -- sam of the start of the arc)
 mapCycle :: (Time -> Time) -> Arc -> Arc
-mapCycle f (Arc s e) = Arc (sam' + (f $ s - sam')) (sam' + (f $ e - sam'))
+mapCycle f (Arc s e) = Arc (sam' + f (s - sam')) (sam' + f (e - sam'))
          where sam' = sam s
 
 -- | @isIn a t@ is @True@ if @t@ is inside
@@ -134,7 +133,7 @@
 type Event a = EventF (ArcF Time) a
 
 instance Bifunctor EventF where
-  bimap f g (Event w p e) = (Event (f w) (f p) (g e))
+  bimap f g (Event w p e) = Event (f w) (f p) (g e)
 
 instance {-# OVERLAPPING #-} Show a => Show (Event a) where
   show (Event (Arc ws we) a@(Arc ps pe) e) =
@@ -151,16 +150,16 @@
 -- | Compares two lists of events, attempting to combine fragmented events in the process
 -- for a 'truer' compare
 compareDefrag :: (Ord a) => [Event a] -> [Event a] -> Bool
-compareDefrag as bs = (sort $ defragParts as) == (sort $ defragParts bs)
+compareDefrag as bs = sort (defragParts as) == sort (defragParts bs)
 
 -- | Returns a list of events, with any adjacent parts of the same whole combined
 defragParts :: Eq a => [Event a] -> [Event a]
 defragParts [] = []
-defragParts (e:[]) = (e:[])
-defragParts (e:es) | isJust i = defraged:(defragParts (delete e' es))
-                   | otherwise = e:(defragParts es)
+defragParts [e] = [e]
+defragParts (e:es) | isJust i = defraged : defragParts (delete e' es)
+                   | otherwise = e : defragParts es
   where i = findIndex (isAdjacent e) es
-        e' = es !! (fromJust i)
+        e' = es !! fromJust i
         defraged = Event (whole e) u (value e)
         u = hull (part e) (part e')
 
@@ -168,9 +167,9 @@
 isAdjacent :: Eq a => Event a -> Event a -> Bool
 isAdjacent e e' = (whole e == whole e')
                   && (value e == value e')
-                  && (((stop $ part e) == (start $ part e'))
+                  && ((stop (part e) == start (part e'))
                       ||
-                      ((stop $ part e') == (start $ part e))
+                      (stop (part e') == start (part e))
                      )
 
 -- | Get the onset of an event's 'whole'
@@ -197,7 +196,7 @@
 eventValue = value
 
 eventHasOnset :: Event a -> Bool
-eventHasOnset e = (start $ whole e) == (start $ part e)
+eventHasOnset e = start (whole e) == start (part e)
 
 toEvent :: (((Time, Time), (Time, Time)), a) -> Event a
 toEvent (((ws, we), (ps, pe)), v) = Event (Arc ws we) (Arc ps pe) v
@@ -231,7 +230,7 @@
 
 instance Functor Pattern where
   -- | apply a function to all the values in a pattern
-  fmap f p = p {query = (fmap (fmap f)) . query p}
+  fmap f p = p {query = fmap (fmap f) . query p}
 
 instance Applicative Pattern where
   -- | Repeat the given value once per cycle, forever
@@ -239,7 +238,7 @@
     map (\a' -> Event a' (sect a a') v) $ cycleArcsInArc a
 
   (<*>) pf@(Pattern Digital _) px@(Pattern Digital _) = Pattern Digital q
-    where q st = catMaybes $ concat $ map match $ query pf st
+    where q st = catMaybes $ concatMap match $ query pf st
             where
               match (Event fWhole fPart f) =
                 map
@@ -254,7 +253,7 @@
             where
               match (Event fWhole fPart f) =
                 map
-                (\e -> (Event fWhole fPart (f (value e))))
+                (Event fWhole fPart . f . value)
                 (query px $ st {arc = pure (start fPart)})
 
   (<*>) pf@(Pattern Analog _) px@(Pattern Digital _) = Pattern Digital q
@@ -262,15 +261,15 @@
             where
               match (Event xWhole xPart x) =
                 map
-                (\e -> (Event xWhole xPart ((value e) x)))
-                (query pf st {arc = (pure (start xPart))})
+                (\e -> Event xWhole xPart (value e x))
+                (query pf st {arc = pure (start xPart)})
 
   (<*>) pf px = Pattern Analog q
     where q st = concatMap match $ query pf st
             where
               match ef =
                 map
-                (\ex -> (Event (arc st) (arc st) ((value ef) (value ex))))
+                (Event (arc st) (arc st) . value ef . value)
                 (query px st)
 
 -- | Like <*>, but the structure only comes from the left
@@ -280,7 +279,7 @@
          where
             match (Event fWhole fPart f) =
               map
-              (\e -> (Event fWhole fPart (f (value e)))) $
+              (Event fWhole fPart . f . value) $
               query px $ st {arc = xQuery fWhole}
             xQuery (Arc s _) = pure s -- for discrete events, match with the onset
 
@@ -289,7 +288,7 @@
           where
             match (Event fWhole fPart f) =
               map
-              (\e -> (Event fWhole fPart (f (value e)))) $
+              (Event fWhole fPart . f . value) $
               query px st -- for continuous events, use the original query
 
 -- | Like <*>, but the structure only comes from the right
@@ -299,7 +298,7 @@
          where
             match (Event xWhole xPart x) =
               map
-              (\e -> (Event xWhole xPart ((value e) x))) $
+              (\e -> Event xWhole xPart (value e x)) $
               query pf $ fQuery xWhole
             fQuery (Arc s _) = st {arc = pure s} -- for discrete events, match with the onset
 
@@ -308,7 +307,7 @@
           where
             match (Event xWhole xPart x) =
               map
-              (\e -> (Event xWhole xPart ((value e) x))) $
+              (\e -> Event xWhole xPart (value e x)) $
               query pf st -- for continuous events, use the original query
 
 infixl 4 <*, *>
@@ -331,9 +330,7 @@
 unwrap pp = pp {query = q}
   where q st = concatMap
           (\(Event w p v) ->
-             catMaybes $
-             map (munge w p) $
-             query v st {arc = p})
+             mapMaybe (munge w p) $ query v st {arc = p})
           (query pp st)
         munge ow op (Event iw ip v') =
           do
@@ -346,10 +343,8 @@
 innerJoin :: Pattern (Pattern a) -> Pattern a
 innerJoin pp = pp {query = q}
   where q st = concatMap
-          (\(Event _ p v) ->
-              catMaybes $
-              map munge $
-              query v st {arc = p})
+               (\(Event _ p v) -> mapMaybe munge $ query v st {arc = p}
+          )
           (query pp st)
           where munge (Event iw ip v) =
                   do
@@ -363,9 +358,8 @@
 outerJoin pp = pp {query = q}
   where q st = concatMap
           (\(Event w p v) ->
-             catMaybes $
-             map (munge w p) $
-             query v st {arc = (pure (start w))})
+             mapMaybe (munge w p) $ query v st {arc = pure (start w)}
+          )
           (query pp st)
           where munge ow op (Event _ _ v') =
                   do
@@ -375,18 +369,18 @@
 -- | Like @unwrap@, but cycles of the inner patterns are compressed to fit the
 -- timespan of the outer whole (or the original query if it's a continuous pattern?)
 -- TODO - what if a continuous pattern contains a discrete one, or vice-versa?
-unwrapSqueeze :: Pattern (Pattern a) -> Pattern a
-unwrapSqueeze pp = pp {query = q}
+squeezeJoin :: Pattern (Pattern a) -> Pattern a
+squeezeJoin pp = pp {query = q}
   where q st = concatMap
           (\(Event w p v) ->
-             catMaybes $
-             map (munge w p) $
-             query (compressArc w v) st {arc = p})
+             mapMaybe (munge w p) $ query (compressArc (cycleArc w) v) st {arc = p}
+          )
           (query pp st)
         munge oWhole oPart (Event iWhole iPart v) =
           do w' <- subArc oWhole iWhole
              p' <- subArc oPart iPart
              return (Event w' p' v)
+        cycleArc (Arc s e) = Arc (cyclePos s) (cyclePos s + (e-s))
 
 noOv :: String -> a
 noOv meth = error $ meth ++ ": not supported for patterns"
@@ -397,18 +391,19 @@
 instance TolerantEq Value where
          (VS a) ~== (VS b) = a == b
          (VI a) ~== (VI b) = a == b
-         (VF a) ~== (VF b) = (abs (a - b)) < 0.000001
+         (VF a) ~== (VF b) = abs (a - b) < 0.000001
          _ ~== _ = False
 
 instance TolerantEq ControlMap where
-  a ~== b = (Map.differenceWith (\a' b' -> if a' ~== b' then Nothing else Just a') a b) == Map.empty
+  a ~== b = Map.differenceWith (\a' b' -> if a' ~== b' then Nothing else Just a') a b == Map.empty
 
 instance TolerantEq (Event ControlMap) where
   (Event w p x) ~== (Event w' p' x') = w == w' && p == p' && x ~== x'
 
-instance TolerantEq a => TolerantEq ([a]) where
-  as ~== bs = (length as == length bs) && (and $ map (\(a,b) -> a ~== b) $ zip as bs)
+instance TolerantEq a => TolerantEq [a] where
+  as ~== bs = (length as == length bs) && all (uncurry (~==)) (zip as bs)
 
+
 instance Eq (Pattern a) where
   (==) = noOv "(==)"
 
@@ -491,13 +486,13 @@
   isIEEE         = noOv "isIEEE"
   atan2          = liftA2 atan2
 
-instance Num (ControlMap) where
-  negate      = ((applyFIS negate negate id) <$>)
+instance Num ControlMap where
+  negate      = (applyFIS negate negate id <$>)
   (+)         = Map.unionWith (fNum2 (+) (+))
   (*)         = Map.unionWith (fNum2 (*) (*))
   fromInteger i = Map.singleton "n" $ VI $ fromInteger i
-  signum      = ((applyFIS signum signum id) <$>)
-  abs         = ((applyFIS abs abs id) <$>)
+  signum      = (applyFIS signum signum id <$>)
+  abs         = (applyFIS abs abs id <$>)
 
 instance Fractional ControlMap where
   recip        = fmap (applyFIS recip id id)
@@ -507,21 +502,21 @@
 showPattern a p = intercalate "\n" $ map show $ queryArc p a
 
 instance (Show a) => Show (Pattern a) where
-  show p = showPattern (Arc 0 1) p
+  show = showPattern (Arc 0 1)
 
 instance Show Value where
   show (VS s) = ('"':s) ++ "\""
   show (VI i) = show i
   show (VF f) = show f ++ "f"
 
-instance {-# OVERLAPPING #-} Show (ControlMap) where
+instance {-# OVERLAPPING #-} Show ControlMap where
   show m = intercalate ", " $ map (\(name, v) -> name ++ ": " ++ show v) $ Map.toList m
 
 prettyRat :: Rational -> String
 prettyRat r | unit == 0 && frac > 0 = showFrac (numerator frac) (denominator frac)
             | otherwise =  show unit ++ showFrac (numerator frac) (denominator frac)
   where unit = floor r :: Int
-        frac = (r - (toRational unit))
+        frac = r - toRational unit
 
 showFrac :: Integer -> Integer -> String
 showFrac 0 _ = ""
@@ -624,7 +619,7 @@
 -- | @withPart f p@ returns a new @Pattern@ with function @f@ applied
 -- to the part.
 withPart :: (Arc -> Arc) -> Pattern a -> Pattern a
-withPart f = withEvent (\(Event w p v) -> (Event w (f p) v))
+withPart f = withEvent (\(Event w p v) -> Event w (f p) v)
 
 -- | Apply one of three functions to a Value, depending on its type
 applyFIS :: (Double -> Double) -> (Int -> Int) -> (String -> String) -> Value -> Value
@@ -660,7 +655,7 @@
                         | otherwise = s `rotR` _fastGap (1/(e-s)) p
 
 compressArcTo :: Arc -> Pattern a -> Pattern a
-compressArcTo (Arc s e) p = compressArc (Arc (cyclePos s) (e-(sam s))) p
+compressArcTo (Arc s e) = compressArc (Arc (cyclePos s) (e - sam s))
 
 _fastGap :: Time -> Pattern a -> Pattern a
 _fastGap 0 _ = empty
@@ -672,7 +667,7 @@
         -- zero width queries of the next sam should return zero in this case..
         f st@(State a _) | start a' == nextSam (start a) = []
                          | otherwise = query p st {arc = a'}
-          where mungeQuery t = sam t + (min 1 $ r' * cyclePos t)
+          where mungeQuery t = sam t + min 1 (r' * cyclePos t)
                 a' = (\(Arc s e) -> Arc (mungeQuery s) (mungeQuery e)) a
 
 -- | Shifts a pattern back in time by the given amount, expressed in cycles
@@ -681,25 +676,25 @@
 
 -- | Shifts a pattern forward in time by the given amount, expressed in cycles
 rotR :: Time -> Pattern a -> Pattern a
-rotR t = rotL (0-t)
+rotR t = rotL (negate t)
 
 -- ** Event filters
 
 -- | Remove events from patterns that to not meet the given test
 filterValues :: (a -> Bool) -> Pattern a -> Pattern a
-filterValues f p = p {query = (filter (f . value)) . query p}
+filterValues f p = p {query = filter (f . value) . query p}
 
 -- | Turns a pattern of 'Maybe' values in to a pattern of values,
 -- dropping the events of 'Nothing'.
 filterJust :: Pattern (Maybe a) -> Pattern a
-filterJust p = fromJust <$> (filterValues (isJust) p)
+filterJust p = fromJust <$> filterValues isJust p
 
 -- formerly known as playWhen
 filterWhen :: (Time -> Bool) -> Pattern a -> Pattern a
 filterWhen test p = p {query = filter (test . wholeStart) . query p}
 
 playFor :: Time -> Time -> Pattern a -> Pattern a
-playFor s e = filterWhen (\t -> and [t >= s, t < e])
+playFor s e = filterWhen (\t -> (t >= s) && (t < e))
 
 -- ** Temporal parameter helpers
 
@@ -713,7 +708,7 @@
 tParam3 f a b c p = innerJoin $ (\x y z -> f x y z p) <$> a <*> b <*> c
 
 tParamSqueeze :: (a -> Pattern b -> Pattern c) -> (Pattern a -> Pattern b -> Pattern c)
-tParamSqueeze f tv p = unwrapSqueeze $ (`f` p) <$> tv
+tParamSqueeze f tv p = squeezeJoin $ (`f` p) <$> tv
 
 -- | Mark values in the first pattern which match with at least one
 -- value in the second pattern.
@@ -722,6 +717,6 @@
   where q st = map match $ query pb st
           where
             match (Event xWhole xPart x) =
-              Event xWhole xPart (or $ (map (f x) (as $ start xWhole)), x)
+              Event xWhole xPart (any (f x) (as $ start xWhole), x)
             as s = map value $ query pa $ fQuery s
-            fQuery s = st {arc = (Arc s s)}
+            fQuery s = st {arc = Arc s s}
diff --git a/src/Sound/Tidal/Scales.hs b/src/Sound/Tidal/Scales.hs
--- a/src/Sound/Tidal/Scales.hs
+++ b/src/Sound/Tidal/Scales.hs
@@ -1,7 +1,6 @@
 module Sound.Tidal.Scales (scale, scaleList) where
 
 import Data.Maybe
-import Data.List (intercalate)
 
 import Sound.Tidal.Pattern
 import Sound.Tidal.Utils
@@ -104,9 +103,9 @@
 melodicMajor :: Num a => [a]
 melodicMajor = [0,2,4,5,7,8,10]
 bartok :: Num a => [a]
-bartok = [0,2,4,5,7,8,10]
+bartok = melodicMajor
 hindu :: Num a => [a]
-hindu = [0,2,4,5,7,8,10]
+hindu = melodicMajor
 
 -- raga modes
 todi :: Num a => [a]
@@ -150,6 +149,22 @@
 diminished2 :: Num a => [a]
 diminished2 = [0,2,3,5,6,8,9,11]
 
+-- modes of limited transposition
+messiaen1 :: Num a => [a]
+messiaen1 = whole'
+messiaen2 :: Num a => [a]
+messiaen2 = diminished
+messiaen3 :: Num a => [a]
+messiaen3 = [0, 2, 3, 4, 6, 7, 8, 10, 11]
+messiaen4 :: Num a => [a]
+messiaen4 = [0, 1, 2, 5, 6, 7, 8, 11]
+messiaen5 :: Num a => [a]
+messiaen5 = [0, 1, 5, 6, 7, 11]
+messiaen6 :: Num a => [a]
+messiaen6 = [0, 2, 4, 5, 6, 8, 10, 11]
+messiaen7 :: Num a => [a]
+messiaen7 = [0, 1, 2, 3, 5, 6, 7, 8, 9, 11]
+
 -- 12 note scales
 chromatic :: Num a => [a]
 chromatic = [0,1,2,3,4,5,6,7,8,9,10,11]
@@ -157,10 +172,10 @@
 scale :: Num a => Pattern String -> Pattern Int -> Pattern a
 scale sp p = (\n scaleName -> noteInScale (fromMaybe [0] $ lookup scaleName scaleTable) n) <$> p <*> sp
   where octave s x = x `div` length s
-        noteInScale s x = (s !!! x) + (fromIntegral $ 12 * octave s x)
+        noteInScale s x = (s !!! x) + fromIntegral (12 * octave s x)
 
 scaleList :: String
-scaleList = intercalate " " $ map fst (scaleTable :: [(String, [Int])])
+scaleList = unwords $ map fst (scaleTable :: [(String, [Int])])
 
 scaleTable :: Num a => [(String, [a])]
 scaleTable = [("minPent", minPent),
@@ -181,6 +196,7 @@
               ("zhi", zhi),
               ("yu", yu),
               ("whole", whole'),
+              ("wholetone", whole'),
               ("augmented", augmented),
               ("augmented2", augmented2),
               ("hexMajor7", hexMajor7),
@@ -221,7 +237,16 @@
               ("neapolitanMajor", neapolitanMajor),
               ("locrianMajor", locrianMajor),
               ("diminished", diminished),
+              ("octatonic", diminished),
               ("diminished2", diminished2),
+              ("octatonic2", diminished2),
+              ("messiaen1", messiaen1),
+              ("messiaen2", messiaen2),
+              ("messiaen3", messiaen3),
+              ("messiaen4", messiaen4),
+              ("messiaen5", messiaen5),
+              ("messiaen6", messiaen6),
+              ("messiaen7", messiaen7),
               ("chromatic", chromatic)
              ]
 
diff --git a/src/Sound/Tidal/Simple.hs b/src/Sound/Tidal/Simple.hs
--- a/src/Sound/Tidal/Simple.hs
+++ b/src/Sound/Tidal/Simple.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
 
 module Sound.Tidal.Simple where
 
@@ -9,7 +9,7 @@
 import Sound.Tidal.Pattern (ControlPattern)
 import GHC.Exts ( IsString(..) )
 
-instance {-# OVERLAPPING #-} IsString (ControlPattern) where
+instance {-# OVERLAPPING #-} IsString ControlPattern where
   fromString = s . parseBP_E
   
 crunch :: ControlPattern -> ControlPattern
diff --git a/src/Sound/Tidal/Tempo.hs b/src/Sound/Tidal/Tempo.hs
--- a/src/Sound/Tidal/Tempo.hs
+++ b/src/Sound/Tidal/Tempo.hs
@@ -37,30 +37,24 @@
                     starting :: Bool
                    }
 
-resetCycles :: MVar Tempo -> IO (Tempo)
-resetCycles tempoMV = do t <- O.time
-                         tempo <- takeMVar tempoMV
-                         let tempo' = tempo {atTime = t,
-                                             atCycle = (-0.5)
-                                            }
-                         sendTempo tempo'
-                         putMVar tempoMV $ tempo'
-                         return tempo'
-
-
-setCps :: MVar Tempo -> O.Time -> IO (Tempo)
-setCps tempoMV newCps = do t <- O.time
+changeTempo :: MVar Tempo -> (O.Time -> Tempo -> Tempo) -> IO Tempo
+changeTempo tempoMV f = do t <- O.time
                            tempo <- takeMVar tempoMV
-                           let c = timeToCycles tempo t
-                               tempo' = tempo {atTime = t,
-                                               atCycle = c,
-                                               cps = newCps
-                                              }
+                           let tempo' = f t $ tempo
                            sendTempo tempo'
-                           -- TODO - should we set the tempo ASAP rather than waiting for (possibly failing) network round trip?
-                           putMVar tempoMV $ tempo'
+                           putMVar tempoMV tempo'
                            return tempo'
 
+
+resetCycles :: MVar Tempo -> IO Tempo
+resetCycles tempoMV = changeTempo tempoMV (\t tempo -> tempo {atTime = t, atCycle = 0})
+
+setCps :: MVar Tempo -> O.Time -> IO Tempo
+setCps tempoMV newCps = changeTempo tempoMV (\t tempo -> tempo {atTime = t,
+                                                                atCycle = timeToCycles tempo t,
+                                                                cps = newCps
+                                                               })
+
 defaultTempo :: O.Time -> O.UDP -> N.SockAddr -> Tempo
 defaultTempo t local remote = Tempo {atTime   = t,
                                      atCycle  = 0,
@@ -75,9 +69,9 @@
 -- | Returns the given time in terms of
 -- cycles relative to metrical grid of a given Tempo
 timeToCycles :: Tempo -> O.Time -> Rational
-timeToCycles tempo t = (atCycle tempo) + (toRational cycleDelta)
-  where delta = t - (atTime tempo)
-        cycleDelta = (realToFrac $ cps tempo) * delta
+timeToCycles tempo t = atCycle tempo + toRational cycleDelta
+  where delta = t - atTime tempo
+        cycleDelta = realToFrac (cps tempo) * delta
 
 {-
 getCurrentCycle :: MVar Tempo -> IO Rational
@@ -94,7 +88,7 @@
        let st = State {ticks = 0,
                        start = s,
                        nowTime = s,
-                       nowArc = (P.Arc 0 0),
+                       nowArc = P.Arc 0 0,
                        starting = True
                       }
        clockTid <- forkIO $ loop tempoMV st
@@ -104,14 +98,14 @@
              tempo <- readMVar tempoMV               
              let frameTimespan = cFrameTimespan config
                  -- 'now' comes from clock ticks, nothing to do with cycles
-                 logicalT ticks' = start st + (fromIntegral ticks') * frameTimespan
-                 logicalNow = logicalT $ (ticks st) + 1
+                 logicalT ticks' = start st + fromIntegral ticks' * frameTimespan
+                 logicalNow = logicalT $ ticks st + 1
                  -- the tempo is just used to convert logical time to cycles
                  e = timeToCycles tempo logicalNow
-                 s = if (starting st) && (synched tempo)
-                     then (timeToCycles tempo (logicalT $ ticks st))
-                     else (P.stop $ nowArc st)
-                 st' = st {ticks = (ticks st) + 1, nowArc = P.Arc s e,
+                 s = if starting st && synched tempo
+                     then timeToCycles tempo (logicalT $ ticks st)
+                     else P.stop $ nowArc st
+                 st' = st {ticks = ticks st + 1, nowArc = P.Arc s e,
                            starting = not (synched tempo)
                           }
              t <- O.time
@@ -128,24 +122,24 @@
      (remote_addr:_) <- N.getAddrInfo Nothing (Just hostname) Nothing
      local <- O.udpServer "127.0.0.1" tempoClientPort
      let (N.SockAddrInet _ a) = N.addrAddress remote_addr
-         remote = N.SockAddrInet (fromIntegral port) (a)
+         remote = N.SockAddrInet (fromIntegral port) a
          t = defaultTempo s local remote
      -- Send to clock port from same port that's listened to
      O.sendTo local (O.p_message "/hello" []) remote
      -- Make tempo mvar
      tempoMV <- newMVar t
      -- Listen to tempo changes
-     tempoChild <- (forkIO $ listenTempo local tempoMV)
+     tempoChild <- forkIO $ listenTempo local tempoMV
      return (tempoMV, tempoChild)
 
 sendTempo :: Tempo -> IO ()
 sendTempo tempo = O.sendTo (localUDP tempo) (O.p_bundle (atTime tempo) [m]) (remoteAddr tempo)
   where m = O.Message "/transmit/cps/cycle" [O.Float $ fromRational $ atCycle tempo,
                                              O.Float $ realToFrac $ cps tempo,
-                                             O.Int32 $ if (paused tempo) then 1 else 0
+                                             O.Int32 $ if paused tempo then 1 else 0
                                             ]
 
-listenTempo :: O.UDP -> (MVar Tempo) -> IO ()
+listenTempo :: O.UDP -> MVar Tempo -> IO ()
 listenTempo udp tempoMV = forever $ do pkt <- O.recvPacket udp
                                        act Nothing pkt
                                        return ()
@@ -160,15 +154,15 @@
              putMVar tempoMV $ tempo {atTime = ts,
                                       atCycle = realToFrac atCycle',
                                       cps = realToFrac cps',
-                                      paused = (paused' == 1),
+                                      paused = paused' == 1,
                                       synched = True
                                      }
         act _ pkt = putStrLn $ "Unknown packet: " ++ show pkt
 
 serverListen :: Config -> IO (Maybe ThreadId)
-serverListen config = catchAny (run) (\_ -> do putStrLn $ "Tempo listener failed (is one already running?)"
-                                               return Nothing
-                                     )
+serverListen config = catchAny run (\_ -> do putStrLn "Tempo listener failed (is one already running?)"
+                                             return Nothing
+                                   )
   where run = do let port = cTempoPort config
                  -- iNADDR_ANY deprecated - what's the right way to do this?
                  udp <- O.udpServer "0.0.0.0" port
@@ -178,11 +172,11 @@
                          cs' <- act udp c Nothing cs pkt
                          loop udp cs'
         act :: O.UDP -> N.SockAddr -> Maybe O.Time -> [N.SockAddr] -> O.Packet -> IO [N.SockAddr]
-        act udp c _ cs (O.Packet_Bundle (O.Bundle ts ms)) = foldM (act udp c (Just ts)) cs $ map (O.Packet_Message) ms
+        act udp c _ cs (O.Packet_Bundle (O.Bundle ts ms)) = foldM (act udp c (Just ts)) cs $ map O.Packet_Message ms
         act _ c _ cs (O.Packet_Message (O.Message "/hello" []))
           = return $ nub $ c:cs
         act udp _ (Just ts) cs (O.Packet_Message (O.Message path params))
-          | isPrefixOf "/transmit" path =
+          | "/transmit" `isPrefixOf` path =
               do let path' = drop 9 path
                      msg = O.Message path' params
                  mapM_ (O.sendTo udp $ O.p_bundle ts [msg]) cs
diff --git a/src/Sound/Tidal/UI.hs b/src/Sound/Tidal/UI.hs
--- a/src/Sound/Tidal/UI.hs
+++ b/src/Sound/Tidal/UI.hs
@@ -4,7 +4,6 @@
 
 import           Prelude hiding ((<*), (*>))
 
-import           Data.Ord (comparing)
 import           Data.Char (digitToInt, isDigit)
 -- import           System.Random (randoms, mkStdGen)
 import           System.Random.MWC
@@ -12,38 +11,36 @@
 import qualified Data.Vector as V
 import           Data.Word (Word32)
 import           Data.Ratio ((%),numerator,denominator)
-import           Data.List (sort, sortBy, sortOn, findIndices, elemIndex, groupBy, transpose)
-import           Data.Maybe (isJust, fromJust, fromMaybe, mapMaybe, catMaybes)
+import           Data.List (sort, sortOn, findIndices, elemIndex, groupBy, transpose)
+import           Data.Maybe (isJust, fromJust, fromMaybe, mapMaybe)
 import qualified Data.Text as T
-import           Control.Applicative (liftA2)
 import qualified Data.Map.Strict as Map
+import           Data.Bool (bool)
 
 import           Sound.Tidal.Bjorklund (bjorklund)
 import           Sound.Tidal.Core
 import qualified Sound.Tidal.Params as P
 import           Sound.Tidal.Pattern
 import           Sound.Tidal.Utils
- 
+
 ------------------------------------------------------------------------
 -- * UI
 
 -- | Randomisation
 
-timeToRand :: RealFrac a => a -> Double
-timeToRand x = runST $ do
+timeToSeed x = do
   let x' = toRational (x*x) / 1000000
   let n' = fromIntegral $ numerator x'
   let d' = fromIntegral $ denominator x'
-  seed <- initialize (V.fromList [n',d'] :: V.Vector Word32)
-  uniform seed
+  initialize (V.fromList [n',d'] :: V.Vector Word32)
 
+timeToRand :: RealFrac a => a -> Double
+timeToRand x = runST $ do seed <- timeToSeed x
+                          uniform seed
+
 timeToRands :: RealFrac a => a -> Int -> [Double]
-timeToRands x n = V.toList $ runST $ do
-  let x' = toRational (x*x) / 1000000
-  let n' = fromIntegral $ numerator x'
-  let d' = fromIntegral $ denominator x'
-  seed <- initialize (V.fromList [n',d'] :: V.Vector Word32)
-  uniformVector seed n
+timeToRands x n = V.toList $ runST $ do seed <- timeToSeed x
+                                        uniformVector seed n
 
 {-|
 
@@ -91,7 +88,7 @@
 @
 -}
 irand :: Num a => Int -> Pattern a
-irand i = (fromIntegral . (floor :: Double -> Int) . (* (fromIntegral i))) <$> rand
+irand i = fromIntegral . (floor :: Double -> Int) . (* fromIntegral i) <$> rand
 
 {- | 1D Perlin (smooth) noise, works like rand but smoothly moves between random
 values each cycle. `perlinWith` takes a pattern as the RNG's "input" instead
@@ -105,8 +102,8 @@
 -}
 perlinWith :: Pattern Double -> Pattern Double
 perlinWith p = interp <$> (p-pa) <*> (timeToRand <$> pa) <*> (timeToRand <$> pb) where
-  pa = ((fromIntegral :: Int -> Double) . floor) <$> p
-  pb = ((fromIntegral :: Int -> Double) . (+1) . floor) <$> p
+  pa = (fromIntegral :: Int -> Double) . floor <$> p
+  pb = (fromIntegral :: Int -> Double) . (+1) . floor <$> p
   interp x a b = a + smootherStep x * (b-a)
   smootherStep x = 6.0 * x**5 - 15.0 * x**4 + 10.0 * x**3
 
@@ -116,9 +113,9 @@
 {- `perlin2With` is Perlin noise with a 2-dimensional input. This can be
 useful for more control over how the randomness repeats (or doesn't).
 @
-d1 
- $ s "[supersaw:-12*32]" 
- # lpf (rangex 60 5000 $ perlin2With (cosine*2) (sine*2)) 
+d1
+ $ s "[supersaw:-12*32]"
+ # lpf (rangex 60 5000 $ perlin2With (cosine*2) (sine*2))
  # lpq 0.3
 @
 will generate a smooth random cutoff pattern that repeats every cycle without
@@ -159,7 +156,7 @@
 
 chooseBy :: Pattern Double -> [a] -> Pattern a
 chooseBy _ [] = silence
-chooseBy f xs = ((xs !!) . floor) <$> (range 0 (fromIntegral $ length xs) f)
+chooseBy f xs = (xs !!) . floor <$> range 0 (fromIntegral $ length xs) f
 
 {- | Like @choose@, but works on an a list of tuples of values and weights
 
@@ -177,7 +174,7 @@
 wchooseBy :: Pattern Double -> [(a,Double)] -> Pattern a
 wchooseBy pat pairs = match <$> pat
   where
-    match r = values !! (head (findIndices (> (r*total)) cweights))
+    match r = values !! head (findIndices (> (r*total)) cweights)
     cweights = scanl1 (+) (map snd pairs)
     values = map fst pairs
     total = sum $ map snd pairs
@@ -207,7 +204,7 @@
 _unDegradeBy x p = fmap fst $ filterValues ((<= x) . snd) $ (,) <$> p <*> rand
 
 degradeOverBy :: Int -> Pattern Double -> Pattern a -> Pattern a
-degradeOverBy i tx p = unwrap $ (\x -> (fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <*> fastRepeatCycles i rand)) <$> (slow (fromIntegral i) tx)
+degradeOverBy i tx p = unwrap $ (\x -> fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <*> fastRepeatCycles i rand) <$> slow (fromIntegral i) tx
 
 
 {- | Use @sometimesBy@ to apply a given function "sometimes". For example, the
@@ -228,7 +225,7 @@
 @
 -}
 sometimesBy :: Pattern Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
-sometimesBy x f p = overlay (degradeBy x p) (f $ unDegradeBy x p)
+sometimesBy x f p = overlay (degradeBy x p) (unDegradeBy x $ f p)
 
 -- | @sometimes@ is an alias for sometimesBy 0.5.
 sometimes :: (Pattern a -> Pattern a) -> Pattern a -> Pattern a
@@ -260,7 +257,7 @@
 `someCycles = someCyclesBy 0.5` alias -}
 someCyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 someCyclesBy x = when test
-  where test c = (timeToRand (fromIntegral c :: Double)) < x
+  where test c = timeToRand (fromIntegral c :: Double) < x
 
 somecyclesBy :: Double -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 somecyclesBy = someCyclesBy
@@ -337,7 +334,7 @@
 iter = tParam _iter
 
 _iter :: Int -> Pattern a -> Pattern a
-_iter n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotL` p) [0 .. (n-1)]
+_iter n p = slowcat $ map (\i -> (fromIntegral i % fromIntegral n) `rotL` p) [0 .. (n-1)]
 
 -- | @iter'@ is the same as @iter@, but decrements the starting
 -- subdivision instead of incrementing it.
@@ -345,7 +342,7 @@
 iter' = tParam _iter'
 
 _iter' :: Int -> Pattern a -> Pattern a
-_iter' n p = slowcat $ map (\i -> ((fromIntegral i)%(fromIntegral n)) `rotR` p) [0 .. (n-1)]
+_iter' n p = slowcat $ map (\i -> (fromIntegral i % fromIntegral n) `rotR` p) [0 .. (n-1)]
 
 -- | @palindrome p@ applies @rev@ to @p@ every other cycle, so that
 -- the pattern alternates between forwards and backwards.
@@ -369,24 +366,24 @@
 @
 -}
 seqP :: [(Time, Time, Pattern a)] -> Pattern a
-seqP ps = stack $ map (\(s, e, p) -> playFor s e ((sam s) `rotR` p)) ps
+seqP ps = stack $ map (\(s, e, p) -> playFor s e (sam s `rotR` p)) ps
 
 -- | Degrades a pattern over the given time.
 fadeOut :: Time -> Pattern a -> Pattern a
-fadeOut dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (_slow dur envL)
+fadeOut dur p = innerJoin $ (`_degradeBy` p) <$> _slow dur envL
 
 -- | Alternate version to @fadeOut@ where you can provide the time from which the fade starts
 fadeOutFrom :: Time -> Time -> Pattern a -> Pattern a
-fadeOutFrom from dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (from `rotR` _slow dur envL)
+fadeOutFrom from dur p = innerJoin $ (`_degradeBy` p) <$> (from `rotR` _slow dur envL)
 
 -- | 'Undegrades' a pattern over the given time.
 fadeIn :: Time -> Pattern a -> Pattern a
-fadeIn dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (_slow dur envLR)
+fadeIn dur p = innerJoin $ (`_degradeBy` p) <$> _slow dur envLR
 
 -- | Alternate version to @fadeIn@ where you can provide the time from
 -- which the fade in starts
 fadeInFrom :: Time -> Time -> Pattern a -> Pattern a
-fadeInFrom from dur p = innerJoin $ (\slope -> _degradeBy slope p) <$> (from `rotR` _slow dur envLR)
+fadeInFrom from dur p = innerJoin $ (`_degradeBy` p) <$> (from `rotR` _slow dur envLR)
 
 {- | The 'spread' function allows you to take a pattern transformation
 which takes a parameter, such as `slow`, and provide several
@@ -453,7 +450,7 @@
 There is also @slowspread@, which is an alias of @spread@.
 -}
 fastspread :: (a -> t -> Pattern b) -> [a] -> t -> Pattern b
-fastspread f xs p = fastcat $ map (\x -> f x p) xs
+fastspread f xs p = fastcat $ map (`f` p) xs
 
 {- | There's a version of this function, `spread'` (pronounced "spread prime"), which takes a *pattern* of parameters, instead of a list:
 
@@ -507,6 +504,8 @@
 -- @p@ into the portion of each cycle given by @t@, and @p'@ into the
 -- remainer of each cycle.
 wedge :: Time -> Pattern a -> Pattern a -> Pattern a
+wedge 0 _ p' = p'
+wedge 1 p _ = p
 wedge t p p' = overlay (_fastGap (1/t) p) (t `rotR` _fastGap (1/(1-t)) p')
 
 {- | @whenmod@ has a similar form and behavior to `every`, but requires an
@@ -522,7 +521,7 @@
 @
 -}
 whenmod :: Int -> Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
-whenmod a b = Sound.Tidal.Core.when ((\t -> (t `mod` a) >= b ))
+whenmod a b = Sound.Tidal.Core.when (\t -> (t `mod` a) >= b )
 
 {- |
 @
@@ -582,7 +581,7 @@
 -}
 within :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 within (s, e) f p = stack [filterWhen (\t -> cyclePos t >= s && cyclePos t < e) $ f p,
-                           filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p
+                           filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) p
                           ]
 
 withinArc :: Arc -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
@@ -623,8 +622,8 @@
 
 within' :: (Time, Time) -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
 within' a@(s, e) f p =
-  stack [ filterWhen (\t -> cyclePos t >= s && cyclePos t < e) $ compress a $ f $ zoom a $ p
-        , filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) $ p
+  stack [ filterWhen (\t -> cyclePos t >= s && cyclePos t < e) $ compress a $ f $ zoom a p
+        , filterWhen (\t -> not $ cyclePos t >= s && cyclePos t < e) p
         ]
 
 revArc :: (Time, Time) -> Pattern a -> Pattern a
@@ -678,8 +677,11 @@
 euclid = tParam2 _euclid
 
 _euclid :: Int -> Int -> Pattern a -> Pattern a
-_euclid n k p = (flip const) <$> (filterValues (== True) $ fastFromList $ bjorklund (n,k)) <*> p
+_euclid n k a = fastcat $ fmap (bool silence a) $ bjorklund (n,k)
 
+-- _euclid :: Int -> Int -> Pattern a -> Pattern a
+-- _euclid n k p = flip const <$> filterValues (== True) (fastFromList $ bjorklund (n,k)) <*> p
+
 {- | `euclidfull n k pa pb` stacks @e n k pa@ with @einv n k pb@ -}
 euclidFull :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a -> Pattern a
 --euclidFull pn pk pa pb = innerJoin $ (\n k -> _euclidFull n k pa pb) <$> pn <*> pk
@@ -688,11 +690,14 @@
 _euclidBool :: Int -> Int -> Pattern Bool
 _euclidBool n k = fastFromList $ bjorklund (n,k)
 
-_euclidFull :: Int -> Int -> Pattern a -> Pattern a -> Pattern a
-_euclidFull n k p p' = pickbool <$> (_euclidBool n k) <*> p <*> p'
-  where pickbool True a _ = a
-        pickbool False _ b = b
+{-_euclidFull :: Int -> Int -> Pattern a -> Pattern a -> Pattern a
+  _euclidFull n k p p' = pickbool <$> _euclidBool n k <*> p <*> p'
+    where pickbool True a _ = a
+          pickbool False _ b = b
+-}
 
+
+
 -- euclid' :: Pattern Int -> Pattern Int -> Pattern a -> Pattern a
 -- euclid' = tParam2 _euclidq'
 
@@ -707,29 +712,29 @@
 
 _euclidOff :: Int -> Int -> Int -> Pattern a -> Pattern a
 _euclidOff _ 0 _ _ = silence
-_euclidOff n k s p = (((fromIntegral s)%(fromIntegral k)) `rotL`) (_euclid n k p)
+_euclidOff n k s p = (rotL $ fromIntegral s%fromIntegral k) (_euclid n k p)
 
 euclidOffBool :: Pattern Int -> Pattern Int -> Pattern Int -> Pattern Bool -> Pattern Bool
 euclidOffBool = tParam3 _euclidOffBool
 
 _euclidOffBool :: Int -> Int -> Int -> Pattern Bool -> Pattern Bool
 _euclidOffBool _ 0 _ _ = silence
-_euclidOffBool n k s p = (((fromIntegral s)%(fromIntegral k)) `rotL`) ((\a b -> if b then a else not a) <$> _euclidBool n k <*> p)
+_euclidOffBool n k s p = ((fromIntegral s % fromIntegral k) `rotL`) ((\a b -> if b then a else not a) <$> _euclidBool n k <*> p)
 
 distrib :: [Pattern Int] -> Pattern a -> Pattern a
 distrib ps p = do p' <- sequence ps
                   _distrib p' p
 
 _distrib :: [Int] -> Pattern a -> Pattern a
-_distrib xs p = boolsToPat (foldr (distrib') (replicate (last xs) True) (reverse $ layers xs)) p
+_distrib xs p = boolsToPat (foldr distrib' (replicate (last xs) True) (reverse $ layers xs)) p
   where
     distrib' :: [Bool] -> [Bool] -> [Bool]
     distrib' [] _ = []
-    distrib' (_:a) [] = False:(distrib' a [])
-    distrib' (True:a) (x:b) = x:(distrib' a b)
-    distrib' (False:a) (b) = False:(distrib' a b)
+    distrib' (_:a) [] = False : distrib' a []
+    distrib' (True:a) (x:b) = x : distrib' a b
+    distrib' (False:a) b = False : distrib' a b
     layers = map bjorklund . (zip<*>tail)
-    boolsToPat a b' = (flip const) <$> (filterValues (== True) $ fastFromList $ a) <*> b'
+    boolsToPat a b' = flip const <$> filterValues (== True) (fastFromList a) <*> b'
 
 {- | `euclidInv` fills in the blanks left by `e`
  -
@@ -741,7 +746,8 @@
 euclidInv = tParam2 _euclidInv
 
 _euclidInv :: Int -> Int -> Pattern a -> Pattern a
-_euclidInv n k p = (flip const) <$> (filterValues (== False) $ fastFromList $ bjorklund (n,k)) <*> p
+--_euclidInv n k p = flip const <$> filterValues (== False) (fastFromList $ bjorklund (n,k)) <*> p
+_euclidInv n k a = fastcat $ fmap (bool a silence) $ bjorklund (n,k)
 
 index :: Real b => b -> Pattern b -> Pattern c -> Pattern c
 index sz indexpat pat =
@@ -866,10 +872,10 @@
                          (drop i $ cycle $ map value es)
                        | otherwise =
                          zipWith (\(Event w p _) s -> Event w p s) es
-                         (drop ((length es) - (abs i)) $ cycle $ map value es)
+                         (drop (length es - abs i) $ cycle $ map value es)
         wholeCycle (Arc s _) = Arc (sam s) (nextSam s)
         constrainEvents :: Arc -> [Event a] -> [Event a]
-        constrainEvents a es = catMaybes $ map (constrainEvent a) es
+        constrainEvents a es = mapMaybe (constrainEvent a) es
         constrainEvent :: Arc -> Event a -> Maybe (Event a)
         constrainEvent a (Event w p v) =
           do
@@ -883,7 +889,7 @@
 segment = tParam _segment
 
 _segment :: Time -> Pattern a -> Pattern a
-_segment n p = (_fast n $ pure (id)) <* p
+_segment n p = _fast n (pure id) <* p
 
 -- | @discretise@: the old (deprecated) name for 'segment'
 discretise :: Pattern Time -> Pattern a -> Pattern a
@@ -892,7 +898,7 @@
 -- | @randcat ps@: does a @slowcat@ on the list of patterns @ps@ but
 -- randomises the order in which they are played.
 randcat :: [Pattern a] -> Pattern a
-randcat ps = spread' (rotL) (_segment 1 $ ((%1) . fromIntegral) <$> (irand (length ps) :: Pattern Int)) (slowcat ps)
+randcat ps = spread' rotL (_segment 1 $ (%1) . fromIntegral <$> (irand (length ps) :: Pattern Int)) (slowcat ps)
 
 -- @fromNote p@: converts a pattern of human-readable pitch names
 -- into pitch numbers. For example, @"cs2"@ will be parsed as C Sharp
@@ -940,14 +946,14 @@
 
 -}
 fit :: Int -> [a] -> Pattern Int -> Pattern a
-fit perCycle xs p = (xs !!!) <$> (p {query = \st -> map ((\e -> (fmap (+ (pos e)) e))) (query p st)})
-  where pos e = perCycle * (floor $ start $ part e)
+fit perCycle xs p = (xs !!!) <$> (p {query = map (\e -> fmap (+ pos e) e) . query p})
+  where pos e = perCycle * floor (start $ part e)
 
 permstep :: RealFrac b => Int -> [a] -> Pattern b -> Pattern a
-permstep nSteps things p = unwrap $ (\n -> fastFromList $ concatMap (\x -> replicate (fst x) (snd x)) $ zip (ps !! (floor (n * (fromIntegral $ (length ps - 1))))) things) <$> (_segment 1 p)
+permstep nSteps things p = unwrap $ (\n -> fastFromList $ concatMap (\x -> replicate (fst x) (snd x)) $ zip (ps !! floor (n * fromIntegral (length ps - 1))) things) <$> _segment 1 p
       where ps = permsort (length things) nSteps
             deviance avg xs = sum $ map (abs . (avg-) . fromIntegral) xs
-            permsort n total = map fst $ sortBy (comparing snd) $ map (\x -> (x,deviance (fromIntegral total / (fromIntegral n :: Double)) x)) $ perms n total
+            permsort n total = map fst $ sortOn snd $ map (\x -> (x,deviance (fromIntegral total / (fromIntegral n :: Double)) x)) $ perms n total
             perms 0 _ = []
             perms 1 n = [[n]]
             perms n total = concatMap (\x -> map (x:) $ perms (n-1) (total-x)) [1 .. (total-(n-1))]
@@ -962,29 +968,29 @@
 substruct :: Pattern String -> Pattern b -> Pattern b
 substruct s p = p {query = f}
   where f st =
-          concatMap (\a' -> queryArc (compressArcTo a' p) a') $ (map whole $ query s st)
+          concatMap ((\a' -> queryArc (compressArcTo a' p) a') . whole) (query s st)
 
 randArcs :: Int -> Pattern [Arc]
 randArcs n =
-  do rs <- mapM (\x -> (pure $ (toRational x)/(toRational n)) <~ choose [1 :: Int,2,3]) [0 .. (n-1)]
+  do rs <- mapM (\x -> pure (toRational x / toRational n) <~ choose [1 :: Int,2,3]) [0 .. (n-1)]
      let rats = map toRational rs
          total = sum rats
-         pairs = pairUp $ accumulate $ map ((/total)) rats
-     return $ pairs
+         pairs = pairUp $ accumulate $ map (/total) rats
+     return pairs
        where pairUp [] = []
-             pairUp xs = (Arc 0 (head xs)):(pairUp' xs)
+             pairUp xs = Arc 0 (head xs) : pairUp' xs
              pairUp' [] = []
-             pairUp' (_:[]) = []
-             pairUp' (a:_:[]) = [Arc a 1]
-             pairUp' (a:b:xs) = (Arc a b):(pairUp' (b:xs))
+             pairUp' [_] = []
+             pairUp' [a, _] = [Arc a 1]
+             pairUp' (a:b:xs) = Arc a b: pairUp' (b:xs)
 
 -- TODO - what does this do? Something for @stripe@ ..
 randStruct :: Int -> Pattern Int
 randStruct n = splitQueries $ Pattern {nature = Digital, query = f}
-  where f st = map (\(a,b,c) -> (Event a (fromJust b) c)) $ filter (\(_,x,_) -> isJust x) $ as
-          where as = map (\(i, (Arc s' e')) ->
-                    (((Arc (s' + sam s) (e' + sam s)),
-                       subArc (Arc s e) (Arc (s' + sam s) (e' + sam s)), i))) $
+  where f st = map (\(a,b,c) -> Event a (fromJust b) c) $ filter (\(_,x,_) -> isJust x) as
+          where as = map (\(i, Arc s' e') ->
+                    (Arc (s' + sam s) (e' + sam s),
+                       subArc (Arc s e) (Arc (s' + sam s) (e' + sam s)), i)) $
                       enumerate $ value $ head $
                       queryArc (randArcs n) (Arc (sam s) (nextSam s))
                 (Arc s e) = arc st
@@ -1035,20 +1041,15 @@
 -}
 lindenmayer :: Int -> String -> String -> String
 lindenmayer _ _ [] = []
-lindenmayer 1 r (c:cs) = (fromMaybe [c] $ lookup c $ parseLMRule' r)
-                         ++ (lindenmayer 1 r cs)
+lindenmayer 1 r (c:cs) = fromMaybe [c] (lookup c $ parseLMRule' r)
+                         ++ lindenmayer 1 r cs
 lindenmayer n r s = iterate (lindenmayer 1 r) s !! n
 
 {- | @lindenmayerI@ converts the resulting string into a a list of integers
 with @fromIntegral@ applied (so they can be used seamlessly where floats or
 rationals are required) -}
 lindenmayerI :: Num b => Int -> String -> String -> [b]
-lindenmayerI n r s = fmap fromIntegral $ fmap digitToInt $ lindenmayer n r s
-
--- support for fit'
-unwrap' :: Pattern (Pattern a) -> Pattern a
-unwrap' pp = pp {query = \st -> query (stack $ map scalep (query pp st)) st}
-  where scalep ev = compressArc (whole ev) $ value ev
+lindenmayerI n r s = fmap (fromIntegral . digitToInt) $ lindenmayer n r s
 
 {-|
 Removes events from second pattern that don't start during an event from first.
@@ -1094,13 +1095,13 @@
 
 -- | TODO: refactor towards union
 enclosingArc :: [Arc] -> Arc
-enclosingArc [] = (Arc 0 1)
+enclosingArc [] = Arc 0 1
 enclosingArc as = Arc (minimum (map start as)) (maximum (map stop as))
 
 stretch :: Pattern a -> Pattern a
 -- TODO - should that be whole or part?
 stretch p = splitQueries $ p {query = q}
-  where q st = query (zoomArc (enclosingArc $ map whole $ query p (st {arc = (Arc (sam s) (nextSam s))})) p) st
+  where q st = query (zoomArc (enclosingArc $ map whole $ query p (st {arc = Arc (sam s) (nextSam s)})) p) st
           where s = start $ arc st
 
 {- | `fit'` is a generalization of `fit`, where the list is instead constructed by using another integer pattern to slice up a given pattern.  The first argument is the number of cycles of that latter pattern to use when slicing.  It's easier to understand this with a few examples:
@@ -1121,11 +1122,11 @@
 
 -}
 fit' :: Pattern Time -> Int -> Pattern Int -> Pattern Int -> Pattern a -> Pattern a
-fit' cyc n from to p = unwrap' $ fit n mapMasks to
+fit' cyc n from to p = squeezeJoin $ fit n mapMasks to
   where mapMasks = [stretch $ mask (const True <$> filterValues (== i) from') p'
                      | i <- [0..n-1]]
-        p' = density cyc $ p
-        from' = density cyc $ from
+        p' = density cyc p
+        from' = density cyc from
 
 {-| @chunk n f p@ treats the given pattern @p@ as having @n@ chunks, and applies the function @f@ to one of those sections per cycle, running from left to right.
 
@@ -1134,7 +1135,7 @@
 @
 -}
 chunk :: Int -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
-chunk n f p = cat [withinArc (Arc (i%(fromIntegral n)) ((i+1)%(fromIntegral n))) f p | i <- [0..(fromIntegral n)-1]]
+chunk n f p = cat [withinArc (Arc (i % fromIntegral n) ((i+1) % fromIntegral n)) f p | i <- [0 .. fromIntegral n - 1]]
 
 {-
 chunk n f p = do i <- _slow (toRational n) $ run (fromIntegral n)
@@ -1149,7 +1150,7 @@
 -}
 chunk' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
 chunk' n f p = do i <- _slow (toRational n) $ rev $ run (fromIntegral n)
-                  withinArc (Arc (i%(fromIntegral n)) ((i+)1%(fromIntegral n))) f p
+                  withinArc (Arc (i % fromIntegral n) ((i+)1 % fromIntegral n)) f p
 
 -- deprecated (renamed to chunk')
 runWith' :: Integral a => a -> (Pattern b -> Pattern b) -> Pattern b -> Pattern b
@@ -1165,10 +1166,10 @@
 loopFirst p = splitQueries $ p {query = f}
   where f st = map
           (\(Event w p' v) ->
-             (Event (plus w) (plus p') v)) $
+             Event (plus w) (plus p') v) $
           query p (st {arc = minus $ arc st})
           where minus = fmap (subtract (sam s))
-                plus = fmap (+ (sam s))
+                plus = fmap (+ sam s)
                 s = start $ arc st
 
 timeLoop :: Pattern Time -> Pattern a -> Pattern a
@@ -1188,7 +1189,7 @@
 toScale' :: Num a => Int -> [a] -> Pattern Int -> Pattern a
 toScale' o s = fmap noteInScale
   where octave x = x `div` length s
-        noteInScale x = (s !!! x) + (fromIntegral $ o * octave x)
+        noteInScale x = (s !!! x) + fromIntegral (o * octave x)
 
 toScale :: Num a => [a] -> Pattern Int -> Pattern a
 toScale = toScale' 12
@@ -1205,54 +1206,55 @@
 
 {- | `cycleChoose` is like `choose` but only picks a new item from the list
 once each cycle -}
-cycleChoose::[a] -> Pattern a
-cycleChoose xs = Pattern {nature = Digital, query = q}
-  where q (State {arc = Arc s e}) = [Event (Arc s e) (Arc s e) (xs!!(floor $ dlen*(ctrand s)))]
-        dlen = fromIntegral $ length xs
-        ctrand s = (timeToRand :: Time -> Double) $ fromIntegral $ (floor :: Time -> Int) $ sam s
+cycleChoose :: [a] -> Pattern a
+cycleChoose = segment 1 . choose
 
+{- | Internal function used by shuffle and scramble -}
+_rearrangeWith :: Pattern Int -> Int -> Pattern a -> Pattern a
+_rearrangeWith ipat n pat = innerJoin $ (\i -> _fast nT $ repeatCycles n $ pats !! i) <$> ipat
+  where
+    pats = map (\i -> zoom (fromIntegral i / nT, fromIntegral (i+1) / nT) pat) [0 .. (n-1)]
+    nT :: Time
+    nT = fromIntegral n
+
 {- | `shuffle n p` evenly divides one cycle of the pattern `p` into `n` parts,
 and returns a random permutation of the parts each cycle.  For example,
 `shuffle 3 "a b c"` could return `"a b c"`, `"a c b"`, `"b a c"`, `"b c a"`,
 `"c a b"`, or `"c b a"`.  But it will **never** return `"a a a"`, because that
 is not a permutation of the parts.
 -}
-shuffle :: Int -> Pattern a -> Pattern a
-shuffle n pat = innerJoin $ (\i -> _fast nT $ repeatCycles n $ pats !! i) <$> randrun n
-  where
-    pats = map (\i -> zoom ((fromIntegral i)/nT, (fromIntegral (i+1))/nT) pat) [0 .. (n-1)]
-    nT :: Time
-    nT = fromIntegral n
+shuffle :: Pattern Int -> Pattern a -> Pattern a
+shuffle = tParam _shuffle
 
+_shuffle :: Int -> Pattern a -> Pattern a
+_shuffle n = _rearrangeWith (randrun n) n
+
 {- | `scramble n p` is like `shuffle` but randomly selects from the parts
 of `p` instead of making permutations.
 For example, `scramble 3 "a b c"` will randomly select 3 parts from
 `"a"` `"b"` and `"c"`, possibly repeating a single part.
 -}
-scramble :: Int -> Pattern a -> Pattern a
-scramble n pat = innerJoin $ (\i -> _fast nT $ repeatCycles n $ pats !! i) <$> randn
-  where
-    randn = _segment nT $ irand n
-    pats = map (\i -> zoom ((fromIntegral i)/nT, (fromIntegral (i+1))/nT) pat) [0 .. (n-1)]
-    nT :: Time
-    nT = fromIntegral n
+scramble :: Pattern Int -> Pattern a -> Pattern a
+scramble = tParam _scramble
 
+_scramble :: Int -> Pattern a -> Pattern a
+_scramble n = _rearrangeWith (_segment (fromIntegral n) $ irand n) n
 
 randrun :: Int -> Pattern Int
 randrun 0 = silence
 randrun n' =
   splitQueries $ Pattern Digital (\(State a@(Arc s _) _) -> events a $ sam s)
-  where events a seed = catMaybes $ map toEvent $ zip arcs shuffled
+  where events a seed = mapMaybe toEv $ zip arcs shuffled
           where shuffled = map snd $ sortOn fst $ zip rs [0 .. (n'-1)]
                 rs = timeToRands seed n'
-                arcs = map (\(s,e) -> Arc s e) $ zip fractions (tail fractions)
-                fractions = map (+ (sam $ start a)) $ [0, 1/(fromIntegral n') .. 1]
-                toEvent (a',v) = do a'' <- subArc a a'
-                                    return $ Event a' a'' v
+                arcs = zipWith Arc fractions (tail fractions)
+                fractions = map (+ (sam $ start a)) [0, 1 / fromIntegral n' .. 1]
+                toEv (a',v) = do a'' <- subArc a a'
+                                 return $ Event a' a'' v
 
 ur :: Time -> Pattern String -> [(String, Pattern a)] -> [(String, Pattern a -> Pattern a)] -> Pattern a
-ur t outer_p ps fs = _slow t $ unwrap $ adjust <$> (timedValues $ (getPat . split) <$> outer_p)
-  where split s = wordsBy (==':') s
+ur t outer_p ps fs = _slow t $ unwrap $ adjust <$> timedValues (getPat . split <$> outer_p)
+  where split = wordsBy (==':')
         getPat (s:xs) = (match s, transform xs)
         -- TODO - check this really can't happen..
         getPat _ = error "can't happen?"
@@ -1261,26 +1263,26 @@
         adjust (a, (p, f)) = f a p
         transform (x:_) a = transform' x a
         transform _ _ = id
-        transform' str (Arc s e) p = s `rotR` (inside (pure $ 1/(e-s)) (matchF str) p)
+        transform' str (Arc s e) p = s `rotR` inside (pure $ 1/(e-s)) (matchF str) p
         matchF str = fromMaybe id $ lookup str fs
         timedValues = withEvent (\(Event a a' v) -> Event a a' (a,v))
 
 inhabit :: [(String, Pattern a)] -> Pattern String -> Pattern a
-inhabit ps p = unwrap' $ (\s -> fromMaybe silence $ lookup s ps) <$> p
+inhabit ps p = squeezeJoin $ (\s -> fromMaybe silence $ lookup s ps) <$> p
 
 {- | @spaceOut xs p@ repeats a pattern @p@ at different durations given by the list of time values in @xs@ -}
 spaceOut :: [Time] -> Pattern a -> Pattern a
-spaceOut xs p = _slow (toRational $ sum xs) $ stack $ map (\a -> compressArc a p) $ spaceArcs
+spaceOut xs p = _slow (toRational $ sum xs) $ stack $ map (`compressArc` p) spaceArcs
   where markOut :: Time -> [Time] -> [Arc]
         markOut _ [] = []
-        markOut offset (x:xs') = (Arc offset (offset+x)):(markOut (offset+x) xs')
-        spaceArcs = map (\(Arc a b) -> (Arc (a/s) (b/s))) $ markOut 0 xs
+        markOut offset (x:xs') = Arc offset (offset+x):markOut (offset+x) xs'
+        spaceArcs = map (\(Arc a b) -> Arc (a/s) (b/s)) $ markOut 0 xs
         s = sum xs
 
 -- | @flatpat@ takes a Pattern of lists and pulls the list elements as
 -- separate Events
 flatpat :: Pattern [a] -> Pattern a
-flatpat p = p {query = \st -> (concatMap (\(Event b b' xs) -> map (\x -> (Event b b' x)) xs) $ query p st)}
+flatpat p = p {query = concatMap (\(Event b b' xs) -> map (Event b b') xs) . query p}
 
 -- | @layer@ takes a Pattern of lists and pulls the list elements as
 -- separate Events
@@ -1298,15 +1300,14 @@
           do
             a'' <- subArc (Arc newS newE) a'
             return (Event (Arc newS newE) a'' v)
-          where newS = s + (dur*(fromIntegral n))
+          where newS = s + (dur * fromIntegral n)
                 newE = newS + dur
-                dur = (e - s) / (fromIntegral d)
+                dur = (e - s) / fromIntegral d
 
 -- | Shorthand alias for arpeggiate
 arpg :: Pattern a -> Pattern a
 arpg = arpeggiate
 
-
 arpWith :: ([EventF (ArcF Time) a] -> [EventF (ArcF Time) b]) -> Pattern a -> Pattern b
 arpWith f p = withEvents munge p
   where munge es = concatMap (spreadOut . f) (groupBy (\a b -> whole a == whole b) es)
@@ -1315,9 +1316,9 @@
           do
             a'' <- subArc (Arc newS newE) a'
             return (Event (Arc newS newE) a'' v)
-          where newS = s + (dur*(fromIntegral n))
+          where newS = s + (dur * fromIntegral n)
                 newE = newS + dur
-                dur = (e - s) / (fromIntegral d)
+                dur = (e - s) / fromIntegral d
 
 arp :: Pattern String -> Pattern a -> Pattern a
 arp = tParam _arp
@@ -1334,16 +1335,16 @@
                 ("down&up", \x -> reverse x ++ x),
                 ("converge", converge),
                 ("diverge", reverse . converge),
-                ("disconverge", \x -> converge x ++ (tail $ reverse $ converge x)),
+                ("disconverge", \x -> converge x ++ tail (reverse $ converge x)),
                 ("pinkyup", pinkyup),
                 ("pinkyupdown", \x -> init (pinkyup x) ++ init (reverse $ pinkyup x)),
                 ("thumbup", thumbup),
                 ("thumbupdown", \x -> init (thumbup x) ++ init (reverse $ thumbup x))
                ]
         converge [] = []
-        converge (x:xs) = x:(converge' xs)
+        converge (x:xs) = x : converge' xs
         converge' [] = []
-        converge' xs = (last xs):(converge $ init xs)
+        converge' xs = last xs : converge (init xs)
         pinkyup xs = concatMap (:[pinky]) $ init xs
           where pinky = last xs
         thumbup xs = concatMap (\x -> [thumb,x]) $ tail xs
@@ -1383,12 +1384,12 @@
 -- patterns.
 sew :: Pattern Bool -> Pattern a -> Pattern a -> Pattern a
 sew stitch p1 p2 = overlay (const <$> p1 <* a) (const <$> p2 <* b)
-  where a = filterValues (id) stitch
-        b = filterValues (not . id) stitch
+  where a = filterValues id stitch
+        b = filterValues not stitch
 
 
 stutter :: Integral i => i -> Time -> Pattern a -> Pattern a
-stutter n t p = stack $ map (\i -> (t * (fromIntegral i)) `rotR` p) [0 .. (n-1)]
+stutter n t p = stack $ map (\i -> (t * fromIntegral i) `rotR` p) [0 .. (n-1)]
 
 echo, triple, quad, double :: Time -> Pattern a -> Pattern a
 echo   = stutter (2 :: Int)
@@ -1452,7 +1453,7 @@
 
 -}
 jux' :: [t -> Pattern ControlMap] -> t -> Pattern ControlMap
-jux' fs p = stack $ map (\n -> ((fs !! n) p) |+ P.pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]
+jux' fs p = stack $ map (\n -> (fs !! n) p |+ P.pan (pure $ fromIntegral n / fromIntegral l)) [0 .. l-1]
   where l = length fs
 
 -- | Multichannel variant of `jux`, _not sure what it does_
@@ -1483,7 +1484,7 @@
 juxBy n f p = stack [p |+ P.pan 0.5 |- P.pan (n/2), f $ p |+ P.pan 0.5 |+ P.pan (n/2)]
 
 pick :: String -> Int -> String
-pick name n = name ++ ":" ++ (show n)
+pick name n = name ++ ":" ++ show n
 
 -- samples "jvbass [~ latibro] [jvbass [latibro jvbass]]" ((1%2) `rotL` slow 6 "[1 6 8 7 3]")
 
@@ -1491,7 +1492,7 @@
 samples p p' = pick <$> p <*> p'
 
 samples' :: Applicative f => f String -> f Int -> f String
-samples' p p' = (flip pick) <$> p' <*> p
+samples' p p' = flip pick <$> p' <*> p
 
 {-
 scrumple :: Time -> Pattern a -> Pattern a -> Pattern a
@@ -1510,7 +1511,7 @@
 
 stackwith :: Unionable a => Pattern a -> [Pattern a] -> Pattern a
 stackwith p ps | null ps = silence
-               | otherwise = stack $ map (\(i, p') -> p' # (((fromIntegral i) % l) `rotL` p)) (zip [0::Int ..] ps)
+               | otherwise = stack $ map (\(i, p') -> p' # ((fromIntegral i % l) `rotL` p)) (zip [0::Int ..] ps)
   where l = fromIntegral $ length ps
 
 {-
@@ -1535,7 +1536,7 @@
   _range from to p
 
 _range :: (Functor f, Num b) => b -> b -> f b -> f b
-_range from to p = ((+ from) . (* (to-from))) <$> p
+_range from to p = (+ from) . (* (to-from)) <$> p
 
 {- | `rangex` is an exponential version of `range`, good for using with
 frequencies.  Do *not* use negative numbers or zero as arguments! -}
@@ -1559,24 +1560,24 @@
               | otherwise = silence
 
 steps :: [(String, String)] -> Pattern String
-steps = stack . map (\(a,b) -> step a b)
+steps = stack . map (uncurry step)
 
 -- | like `step`, but allows you to specify an array of strings to use for 0,1,2...
 step' :: [String] -> String -> Pattern String
 step' ss cs = fastcat $ map f cs
     where f c | c == 'x' = pure $ head ss
-              | isDigit c = pure $ ss!!(digitToInt c)
+              | isDigit c = pure $ ss !! digitToInt c
               | otherwise = silence
 
 
 ghost'' :: Time -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
-ghost'' a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) $ p
+ghost'' a f p = superimpose (((a*2.5) `rotR`) . f) $ superimpose (((a*1.5) `rotR`) . f) p
 
 ghost' :: Time -> Pattern ControlMap -> Pattern ControlMap
 ghost' a p = ghost'' a ((|*| P.gain (pure 0.7)) . (|> P.end (pure 0.2)) . (|*| P.speed (pure 1.25))) p
 
 ghost :: Pattern ControlMap -> Pattern ControlMap
-ghost p = ghost' 0.125 p
+ghost = ghost' 0.125
 
 {- |
    tabby - A more literal weaving than the `weave` function, give number
@@ -1589,16 +1590,16 @@
                      ]
   where
     n = fromIntegral nInt
-    weft = concatMap (\_ -> [[0..n-1],(reverse [0..n-1])]) [0 .. (n `div` 2) - 1]
+    weft = concatMap (const [[0..n-1], reverse [0..n-1]]) [0 .. (n `div` 2) - 1]
     warp = transpose weft
     thread xs p'' = _slow (n%1) $ fastcat $ map (\i -> zoomArc (Arc (i%n) ((i+1)%n)) p'') (concat xs)
     weftP = thread weft p'
     warpP = thread warp p
-    maskedWeft = mask (every 2 rev $ _fast ((n)%2) $ fastCat [silence, pure True]) weftP
-    maskedWarp = mask (every 2 rev $ _fast ((n)%2) $ fastCat [pure True, silence]) warpP
+    maskedWeft = mask (every 2 rev $ _fast (n % 2) $ fastCat [silence, pure True]) weftP
+    maskedWarp = mask (every 2 rev $ _fast (n % 2) $ fastCat [pure True, silence]) warpP
 
 _select :: Double -> [Pattern a] -> Pattern a
-_select f ps =  ps !! (floor $ (max 0 $ min 1 f) * (fromIntegral $ length ps - 1))
+_select f ps =  ps !! floor (max 0 (min 1 f) * fromIntegral (length ps - 1))
 
 -- | chooses between a list of patterns, using a pattern of floats (from 0-1)
 select :: Pattern Double -> [Pattern a] -> Pattern a
@@ -1610,7 +1611,7 @@
 selectF pf ps p = innerJoin $ (\f -> _selectF f ps p) <$> pf
 
 _selectF :: Double -> [Pattern a -> Pattern a] -> Pattern a -> Pattern a
-_selectF f ps p =  (ps !! (floor $ (max 0 $ min 0.999999 f) * (fromIntegral $ length ps))) p
+_selectF f ps p =  (ps !! floor (max 0 (min 0.999999 f) * fromIntegral (length ps))) p
 
 -- | @contrast p f f' p'@ splits controlpattern @p'@ in two, applying
 -- the function @f@ to one and @f'@ to the other. This depends on
@@ -1644,8 +1645,8 @@
      -> ControlPattern
      -> Pattern a
 contrastRange = contrastBy f
-      where f (VI s, VI e) (VI v) = v >= s && v <= e 
-            f (VF s, VF e) (VF v) = v >= s && v <= e 
+      where f (VI s, VI e) (VI v) = v >= s && v <= e
+            f (VF s, VF e) (VF v) = v >= s && v <= e
             f (VS s, VS e) (VS v) = v == s && v == e
             f _ _ = False
 
@@ -1656,7 +1657,7 @@
 -- | Like @contrast@, but one function is given, and applied to events
 -- with controls which don't match.
 unfix :: (ControlPattern -> ControlPattern) -> ControlPattern -> ControlPattern -> ControlPattern
-unfix f = contrast id f
+unfix = contrast id
 
 fixRange :: (ControlPattern -> Pattern ControlMap)
             -> Pattern (Map.Map String (Value, Value))
@@ -1668,7 +1669,7 @@
               -> Pattern (Map.Map String (Value, Value))
               -> ControlPattern
               -> Pattern ControlMap
-unfixRange f = contrastRange id f
+unfixRange = contrastRange id
 
 -- | limit values in a Pattern (or other Functor) to n equally spaced
 -- divisions of 1.
@@ -1682,13 +1683,13 @@
 -- | Serialises a pattern so there's only one event playing at any one
 -- time, making it 'monophonic'. Events which start/end earlier are given priority.
 mono :: Pattern a -> Pattern a
-mono p = Pattern Digital $ \(State a cm) -> flatten $ (query p) (State a cm) where
+mono p = Pattern Digital $ \(State a cm) -> flatten $ query p (State a cm) where
   flatten :: [Event a] -> [Event a]
-  flatten = catMaybes . map constrainPart . truncateOverlaps . sortBy (comparing whole)
+  flatten = mapMaybe constrainPart . truncateOverlaps . sortOn whole
   truncateOverlaps [] = []
-  truncateOverlaps (e:es) = e:(truncateOverlaps $ catMaybes $ map (snip e) es)
-  snip a b | (start $ whole b) >= (stop $ whole a) = Just b
-           | (stop $ whole b) <= (stop $ whole a) = Nothing
+  truncateOverlaps (e:es) = e : truncateOverlaps (mapMaybe (snip e) es)
+  snip a b | start (whole b) >= stop (whole a) = Just b
+           | stop (whole b) <= stop (whole a) = Nothing
            | otherwise = Just b {whole = Arc (stop $ whole a) (stop $ whole b)}
   constrainPart :: Event a -> Maybe (Event a)
   constrainPart e = do a <- subArc (whole e) (part e)
@@ -1718,11 +1719,21 @@
                 , part = queryA'
                 , value = value e + ((v - value e) * pc)}
               ]
-            pc | (delta' $ whole e) == 0 = 0
-               | otherwise = fromRational $ (eventPartStart e - wholeStart e) / (delta' $ whole e)
+            pc | delta' (whole e) == 0 = 0
+               | otherwise = fromRational $ (eventPartStart e - wholeStart e) / delta' (whole e)
             delta' a = stop a - start a
     monoP = mono p
 
 -- | Looks up values from a list of tuples, in order to swap values in the given pattern
 swap :: Eq a => [(a, b)] -> Pattern a -> Pattern b
-swap things p = filterJust $ (\x -> lookup x things) <$> p
+swap things p = filterJust $ (`lookup` things) <$> p
+
+{- @coat@ | 
+    applies a function to a pattern and cats the resulting pattern,
+    then continues applying the function until the depth is reached
+    this can be used to create a pattern that wanders away from 
+    the original pattern by continually adding random numbers
+    d1 $ note (scale "hexDorian" mutateBy (+ (range -1 1 $ irand 2)) 8 $ "0 1 . 2 3 4") # s "gtr"
+-}
+soak ::  Int -> (Pattern a -> Pattern a) -> Pattern a -> Pattern a
+soak depth f pattern = cat $ take depth $ iterate f pattern
diff --git a/src/Sound/Tidal/Utils.hs b/src/Sound/Tidal/Utils.hs
--- a/src/Sound/Tidal/Utils.hs
+++ b/src/Sound/Tidal/Utils.hs
@@ -6,7 +6,7 @@
 mapBoth f (a,b) = (f a, f b)
 
 mapPartTimes :: (a -> a) -> ((a,a),(a,a)) -> ((a,a),(a,a))
-mapPartTimes f part = mapBoth (mapBoth f) part
+mapPartTimes f = mapBoth (mapBoth f)
 
 mapFst :: (a -> b) -> (a, c) -> (b, c)
 mapFst f (x,y) = (f x,y)
@@ -24,7 +24,7 @@
 removeCommon :: Eq a => [a] -> [a] -> ([a],[a])
 removeCommon [] bs = ([],bs)
 removeCommon as [] = (as,[])
-removeCommon (a:as) bs | elem a bs = removeCommon as (delete a bs)
+removeCommon (a:as) bs | a `elem` bs = removeCommon as (delete a bs)
                        | otherwise = (a:as',bs')
                       where (as',bs') = removeCommon as bs
 
@@ -51,7 +51,7 @@
 accumulate :: Num t => [t] -> [t]
 accumulate = accumulate' 0
   where accumulate' _ [] = []
-        accumulate' n (a:xs) = (n+a):(accumulate' (n+a) xs)
+        accumulate' n (a:xs) = (n+a) : accumulate' (n+a) xs
 
 {- | enumerate a list of things
 
diff --git a/src/Sound/Tidal/Version.hs b/src/Sound/Tidal/Version.hs
--- a/src/Sound/Tidal/Version.hs
+++ b/src/Sound/Tidal/Version.hs
@@ -1,4 +1,4 @@
-
 module Sound.Tidal.Version where
 
+tidal_version :: String
 tidal_version = "1.0.7"
diff --git a/test/Sound/Tidal/PatternTest.hs b/test/Sound/Tidal/PatternTest.hs
--- a/test/Sound/Tidal/PatternTest.hs
+++ b/test/Sound/Tidal/PatternTest.hs
@@ -194,12 +194,12 @@
                       (Event (Arc (2 % 3) (1 % 1)) (Arc (2 % 3) (1 % 1)) "e")
                      ]
 
-    describe "unwrapSqueeze" $ do
+    describe "squeezeJoin" $ do
       it "compresses cycles to fit outer 'whole' timearc of event" $ do
         let a = fastCat [pure "a", pure "b"]
             b = fastCat [pure "c", pure "d", pure "e"]
             pp = fastCat [pure a, pure b]
-        queryArc (unwrapSqueeze pp) (Arc 0 1)
+        queryArc (squeezeJoin pp) (Arc 0 1)
           `shouldBe` [(Event (Arc (0 % 1) (1 % 4)) (Arc (0 % 1) (1 % 4)) ("a" :: String)),
                       (Event (Arc (1 % 4) (1 % 2)) (Arc (1 % 4) (1 % 2)) "b"),
                       (Event (Arc (1 % 2) (2 % 3)) (Arc (1 % 2) (2 % 3)) "c"),
diff --git a/test/Sound/Tidal/ScalesTest.hs b/test/Sound/Tidal/ScalesTest.hs
new file mode 100644
--- /dev/null
+++ b/test/Sound/Tidal/ScalesTest.hs
@@ -0,0 +1,318 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Sound.Tidal.ScalesTest where
+
+import TestUtils
+import Test.Microspec
+
+import Prelude hiding ((<*), (*>))
+
+import Sound.Tidal.Scales
+import Sound.Tidal.Pattern
+
+run :: Microspec ()
+run =
+  describe "Sound.Tidal.Scales" $ do
+    describe "scale" $ do
+        describe "5 note scales" $ do
+            let twoOctavesOf5NoteScale = "0 1 2 3 4 5 6 7 8 9"
+            it "can transform notes correctly over 2 octaves - minPent" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "minPent" twoOctavesOf5NoteScale)
+                    ("0 3 5 7 10 12 15 17 19 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - majPent" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "majPent" twoOctavesOf5NoteScale)
+                    ("0 2 4 7 9 12 14 16 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - ritusen" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "ritusen" twoOctavesOf5NoteScale)
+                    ("0 2 5 7 9 12 14 17 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - egyptian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "egyptian" twoOctavesOf5NoteScale)
+                    ("0 2 5 7 10 12 14 17 19 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - kumai" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "kumai" twoOctavesOf5NoteScale)
+                    ("0 2 3 7 9 12 14 15 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hirajoshi" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hirajoshi" twoOctavesOf5NoteScale)
+                    ("0 2 3 7 8 12 14 15 19 20"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - iwato" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "iwato" twoOctavesOf5NoteScale)
+                    ("0 1 5 6 10 12 13 17 18 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - chinese" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "chinese" twoOctavesOf5NoteScale)
+                    ("0 4 6 7 11 12 16 18 19 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - indian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "indian" twoOctavesOf5NoteScale)
+                    ("0 4 5 7 10 12 16 17 19 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - pelog" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "pelog" twoOctavesOf5NoteScale)
+                    ("0 1 3 7 8 12 13 15 19 20"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - prometheus" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "prometheus" twoOctavesOf5NoteScale)
+                    ("0 2 4 6 11 12 14 16 18 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - scriabin" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "scriabin" twoOctavesOf5NoteScale)
+                    ("0 1 4 7 9 12 13 16 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - gong" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "gong" twoOctavesOf5NoteScale)
+                    ("0 2 4 7 9 12 14 16 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - shang" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "shang" twoOctavesOf5NoteScale)
+                    ("0 2 5 7 10 12 14 17 19 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - jiao" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "jiao" twoOctavesOf5NoteScale)
+                    ("0 3 5 8 10 12 15 17 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - zhi" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "zhi" twoOctavesOf5NoteScale)
+                    ("0 2 5 7 9 12 14 17 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - yu" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "yu" twoOctavesOf5NoteScale)
+                    ("0 3 5 7 10 12 15 17 19 22"::Pattern Int)
+        describe "6 note scales" $ do
+            let twoOctavesOf6NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11"
+            it "can transform notes correctly over 2 octaves - whole" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "whole" twoOctavesOf6NoteScale)
+                    ("0 2 4 6 8 10 12 14 16 18 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - wholetone" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "wholetone" twoOctavesOf6NoteScale)
+                    (Sound.Tidal.Scales.scale "whole" twoOctavesOf6NoteScale :: Pattern Int)
+            it "can transform notes correctly over 2 octaves - augmented" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "augmented" twoOctavesOf6NoteScale)
+                    ("0 3 4 7 8 11 12 15 16 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - augmented2" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "augmented2" twoOctavesOf6NoteScale)
+                    ("0 1 4 5 8 9 12 13 16 17 20 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexMajor7" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexMajor7" twoOctavesOf6NoteScale)
+                    ("0 2 4 7 9 11 12 14 16 19 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexPhrygian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexPhrygian" twoOctavesOf6NoteScale)
+                    ("0 1 3 5 8 10 12 13 15 17 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexDorian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexDorian" twoOctavesOf6NoteScale)
+                    ("0 2 3 5 7 10 12 14 15 17 19 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexSus" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexSus" twoOctavesOf6NoteScale)
+                    ("0 2 5 7 9 10 12 14 17 19 21 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexMajor6" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexMajor6" twoOctavesOf6NoteScale)
+                    ("0 2 4 5 7 9 12 14 16 17 19 21"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hexAeolian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hexAeolian" twoOctavesOf6NoteScale)
+                    ("0 3 5 7 8 10 12 15 17 19 20 22"::Pattern Int)
+        describe "7 note scales" $ do
+            let twoOctavesOf7NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13"
+            it "can transform notes correctly over 2 octaves - major" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "major" twoOctavesOf7NoteScale)
+                    ("0 2 4 5 7 9 11 12 14 16 17 19 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - ionian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "ionian" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "major" twoOctavesOf7NoteScale :: Pattern Int)
+            it "can transform notes correctly over 2 octaves - dorian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "dorian" twoOctavesOf7NoteScale)
+                    ("0 2 3 5 7 9 10 12 14 15 17 19 21 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - aeolian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "aeolian" twoOctavesOf7NoteScale)
+                    ("0 2 3 5 7 8 10 12 14 15 17 19 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - aeolian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "minor" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "aeolian" twoOctavesOf7NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - minor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "minor" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "aeolian" twoOctavesOf7NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - locrian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "locrian" twoOctavesOf7NoteScale)
+                    ("0 1 3 5 6 8 10 12 13 15 17 18 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - harmonicMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "harmonicMinor" twoOctavesOf7NoteScale)
+                    ("0 2 3 5 7 8 11 12 14 15 17 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - harmonicMajor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "harmonicMajor" twoOctavesOf7NoteScale)
+                    ("0 2 4 5 7 8 11 12 14 16 17 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - melodicMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "melodicMinor" twoOctavesOf7NoteScale)
+                    ("0 2 3 5 7 9 11 12 14 15 17 19 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - melodicMinorDesc" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "melodicMinorDesc" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "minor" twoOctavesOf7NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - melodicMajor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "melodicMajor" twoOctavesOf7NoteScale)
+                    ("0 2 4 5 7 8 10 12 14 16 17 19 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - bartok" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "bartok" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "melodicMajor" twoOctavesOf7NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hindu" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hindu" twoOctavesOf7NoteScale)
+                    (Sound.Tidal.Scales.scale "melodicMajor" twoOctavesOf7NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - todi" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "todi" twoOctavesOf7NoteScale)
+                    ("0 1 3 6 7 8 11 12 13 15 18 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - purvi" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "purvi" twoOctavesOf7NoteScale)
+                    ("0 1 4 6 7 8 11 12 13 16 18 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - marva" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "marva" twoOctavesOf7NoteScale)
+                    ("0 1 4 6 7 9 11 12 13 16 18 19 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - bhairav" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "bhairav" twoOctavesOf7NoteScale)
+                    ("0 1 4 5 7 8 11 12 13 16 17 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - ahirbhairav" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "ahirbhairav" twoOctavesOf7NoteScale)
+                    ("0 1 4 5 7 9 10 12 13 16 17 19 21 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - superLocrian" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "superLocrian" twoOctavesOf7NoteScale)
+                    ("0 1 3 4 6 8 10 12 13 15 16 18 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - romanianMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "romanianMinor" twoOctavesOf7NoteScale)
+                    ("0 2 3 6 7 9 10 12 14 15 18 19 21 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - hungarianMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "hungarianMinor" twoOctavesOf7NoteScale)
+                    ("0 2 3 6 7 8 11 12 14 15 18 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - neapolitanMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "neapolitanMinor" twoOctavesOf7NoteScale)
+                    ("0 1 3 5 7 8 11 12 13 15 17 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - enigmatic" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "enigmatic" twoOctavesOf7NoteScale)
+                    ("0 1 4 6 8 10 11 12 13 16 18 20 22 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - spanish" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "spanish" twoOctavesOf7NoteScale)
+                    ("0 1 4 5 7 8 10 12 13 16 17 19 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - leadingWhole" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "leadingWhole" twoOctavesOf7NoteScale)
+                    ("0 2 4 6 8 10 11 12 14 16 18 20 22 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - lydianMinor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "lydianMinor" twoOctavesOf7NoteScale)
+                    ("0 2 4 6 7 8 10 12 14 16 18 19 20 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - neapolitanMajor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "neapolitanMajor" twoOctavesOf7NoteScale)
+                    ("0 1 3 5 7 9 11 12 13 15 17 19 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - locrianMajor" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "locrianMajor" twoOctavesOf7NoteScale)
+                    ("0 2 4 5 6 8 10 12 14 16 17 18 20 22"::Pattern Int)
+        describe "8 note scales" $ do
+            let twoOctavesOf8NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+            it "can transform notes correctly over 2 octaves - diminished" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "diminished" twoOctavesOf8NoteScale)
+                    ("0 1 3 4 6 7 9 10 12 13 15 16 18 19 21 22"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - octatonic" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "octatonic" twoOctavesOf8NoteScale)
+                    (Sound.Tidal.Scales.scale "diminished" twoOctavesOf8NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - diminished2" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "diminished2" twoOctavesOf8NoteScale)
+                    ("0 2 3 5 6 8 9 11 12 14 15 17 18 20 21 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - octatonic2" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "octatonic2" twoOctavesOf8NoteScale)
+                    (Sound.Tidal.Scales.scale "diminished2" twoOctavesOf8NoteScale::Pattern Int)
+        describe "modes of limited transposition" $ do
+            let twoOctavesOf6NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11"
+            let twoOctavesOf8NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+            let twoOctavesOf9NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17"
+            let twoOctavesOf10NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19"
+            it "can transform notes correctly over 2 octaves - messiaen1" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen1" twoOctavesOf6NoteScale)
+                    (Sound.Tidal.Scales.scale "wholetone" twoOctavesOf6NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen2" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen2" twoOctavesOf8NoteScale)
+                    (Sound.Tidal.Scales.scale "diminished" twoOctavesOf8NoteScale::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen3" $ do
+                -- tone, semitone, semitone, tone, semitone, semitone, tone, semitone, semitone
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen3" twoOctavesOf9NoteScale)
+                    ("0 2 3 4 6 7 8 10 11 12 14 15 16 18 19 20 22 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen4" $ do
+                -- semitone, semitone, minor third, semitone, semitone, semitone, minor third, semitone
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen4" twoOctavesOf8NoteScale)
+                    ("0 1 2 5 6 7 8 11 12 13 14 17 18 19 20 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen5" $ do
+                -- semitone, major third, semitone, semitone, major third, semitone
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen5" twoOctavesOf6NoteScale)
+                    ("0 1 5 6 7 11 12 13 17 18 19 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen6" $ do
+                -- tone, tone, semitone, semitone, tone, tone, semitone, semitone
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen6" twoOctavesOf8NoteScale)
+                    ("0 2 4 5 6 8 10 11 12 14 16 17 18 20 22 23"::Pattern Int)
+            it "can transform notes correctly over 2 octaves - messiaen7" $ do
+                -- semitone, semitone, semitone, tone, semitone, semitone, semitone, semitone, tone, semitone
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "messiaen7" twoOctavesOf10NoteScale)
+                    ("0 1 2 3 5 6 7 8 9 11 12 13 14 15 17 18 19 20 21 23"::Pattern Int)
+        describe "12 note scales" $ do
+            let twoOctavesOf12NoteScale = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23"
+            it "can transform notes correctly over 2 octaves - chromatic" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "chromatic" twoOctavesOf12NoteScale)
+                    (twoOctavesOf12NoteScale::Pattern Int)
+        describe "edge cases" $ do
+            it "responds to unknown scales by mapping to octaves" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "ergaerv" "0 1 2 3 4")
+                    ("0 12 24 36 48"::Pattern Int)
+            it "correctly maps negative numbers" $ do
+                compareP (Arc 0 1)
+                    (Sound.Tidal.Scales.scale "major" "0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13")
+                    ("0 -1 -3 -5 -7 -8 -10 -12 -13 -15 -17 -19 -20 -22 "::Pattern Int)
+           
diff --git a/test/Sound/Tidal/UITest.hs b/test/Sound/Tidal/UITest.hs
--- a/test/Sound/Tidal/UITest.hs
+++ b/test/Sound/Tidal/UITest.hs
@@ -13,6 +13,7 @@
 import Sound.Tidal.Control
 import Sound.Tidal.Core
 import Sound.Tidal.Params
+import Sound.Tidal.ParseBP
 import Sound.Tidal.Pattern
 import Sound.Tidal.UI
 
@@ -58,6 +59,14 @@
           in
             compareP overTimeSpan testMe expectedResult
 
+      it "does nothing when set at 0% probability -- const" $ do
+        let
+          overTimeSpan = (Arc 0  2)
+          testMe = sometimesBy 0 (const $ s "cp") (s "bd*8")
+          expectedResult = s "bd*8"
+          in
+            compareP overTimeSpan testMe expectedResult
+
       it "applies the 'rev' function when set at 100% probability" $ do
         let
           overTimeSpan = (Arc 0  1)
@@ -169,3 +178,62 @@
         compareP (Arc 0 1)
           (euclidFull 3 8 "bd" silence)
           ("bd(3,8)" :: Pattern String)
+          
+    describe "soak" $ do
+      it "applies a transform and then appends the result -- addition" $ do
+        compareP (Arc 0 3)
+          (soak 3 (+ 1) "4 ~ 0 1")
+          (cat ["4 ~ 0 1"::Pattern Int,"5 ~ 1 2"::Pattern Int,"6 ~ 2 3"::Pattern Int])
+      it "applies a transform and then appends the result -- slow" $ do
+        compareP (Arc 0 7)
+          (soak 3 (slow 2) "4 ~ 0 1")
+          (cat ["4 ~ 0 1"::Pattern Int, slow 2 "4 ~ 0 1"::Pattern Int, slow 4 "4 ~  0 1"::Pattern Int])
+      it "applies a transform and then appends the result -- addition patterns" $ do
+        compareP (Arc 0 3)
+          (soak 3 (+ "1 2 3") "1 1")
+          (cat ["1 1"::Pattern Int,"2 [3 3] 4"::Pattern Int,"3 [5 5] 7"::Pattern Int])
+
+    describe "euclid" $ do
+      it "matches examples in Toussaint's paper" $ do
+        sequence_ $ map (\(a,b) -> it b $ compareP (Arc 0 1) a (parseBP_E b))
+          ([(euclid 1 2 "x", "x ~"),
+            (euclid 1 3 "x", "x ~ ~"),
+            (euclid 1 4 "x", "x ~ ~ ~"),
+            (euclid 4 12 "x", "x ~ ~ x ~ ~ x ~ ~ x ~ ~"),
+            (euclid 2 5 "x", "x ~ x ~ ~"),
+            -- (euclid 3 4 "x", "x ~ x x"), -- Toussaint is wrong..
+            (euclid 3 4 "x", "x x x ~"), -- correction
+            (euclid 3 5 "x", "x ~ x ~ x"),
+            (euclid 3 7 "x", "x ~ x ~ x ~ ~"),
+            (euclid 3 8 "x", "x ~ ~ x ~ ~ x ~"),
+            (euclid 4 7 "x", "x ~ x ~ x ~ x"),
+            (euclid 4 9 "x", "x ~ x ~ x ~ x ~ ~"),
+            (euclid 4 11 "x", "x ~ ~ x ~ ~ x ~ ~ x ~"),
+            -- (euclid 5 6 "x", "x ~ x x x x"), -- Toussaint is wrong..
+            (euclid 5 6 "x", "x x x x x ~"),  -- correction
+            (euclid 5 7 "x", "x ~ x x ~ x x"),
+            (euclid 5 8 "x", "x ~ x x ~ x x ~"),
+            (euclid 5 9 "x", "x ~ x ~ x ~ x ~ x"),
+            (euclid 5 11 "x", "x ~ x ~ x ~ x ~ x ~ ~"),
+            (euclid 5 12 "x", "x ~ ~ x ~ x ~ ~ x ~ x ~"),
+            -- (euclid 5 16 "x", "x ~ ~ x ~ ~ x ~ ~ x ~ ~ x ~ ~ ~ ~"),  -- Toussaint is wrong..
+            (euclid 5 16 "x", "x ~ ~ x ~ ~ x ~ ~ x ~ ~ x ~ ~ ~"), -- correction
+            -- (euclid 7 8 "x", "x ~ x x x x x x"), -- Toussaint is wrong..
+            (euclid 7 8 "x", "x x x x x x x ~"), -- Correction
+            (euclid 7 12 "x", "x ~ x x ~ x ~ x x ~ x ~"),
+            (euclid 7 16 "x", "x ~ ~ x ~ x ~ x ~ ~ x ~ x ~ x ~"),
+            (euclid 9 16 "x", "x ~ x x ~ x ~ x ~ x x ~ x ~ x ~"),
+            (euclid 11 24 "x", "x ~ ~ x ~ x ~ x ~ x ~ x ~ ~ x ~ x ~ x ~ x ~ x ~"),
+            (euclid 13 24 "x", "x ~ x x ~ x ~ x ~ x ~ x ~ x x ~ x ~ x ~ x ~ x ~")
+          ] :: [(Pattern String, String)])
+
+    describe "wedge" $ do
+      it "should not freeze tidal amount is 1" $ do
+        compareP (Arc 0 1)
+          (wedge (1) (s "ho ho:2 ho:3 hc") (rev $ s "ho ho:2 ho:3 hc"))
+          (s "ho ho:2 ho:3 hc")
+      it "should not freeze tidal amount is 0" $ do
+        compareP (Arc 0 1)
+          (wedge (0) (s "ho ho:2 ho:3 hc") (rev $ s "ho ho:2 ho:3 hc"))
+          (rev $ s "ho ho:2 ho:3 hc")
+
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -7,6 +7,7 @@
 import Sound.Tidal.ParseTest
 import Sound.Tidal.PatternTest
 import Sound.Tidal.ControlTest
+import Sound.Tidal.ScalesTest
 import Sound.Tidal.UITest
 import Sound.Tidal.UtilsTest
 
@@ -17,5 +18,6 @@
   Sound.Tidal.ParseTest.run
   Sound.Tidal.PatternTest.run
   Sound.Tidal.ControlTest.run
+  Sound.Tidal.ScalesTest.run
   Sound.Tidal.UITest.run
   Sound.Tidal.UtilsTest.run
diff --git a/tidal.cabal b/tidal.cabal
--- a/tidal.cabal
+++ b/tidal.cabal
@@ -1,5 +1,5 @@
 name:                tidal
-version:             1.0.7
+version:             1.0.8
 synopsis:            Pattern language for improvised music
 -- description:
 homepage:            http://tidalcycles.org/
@@ -19,9 +19,6 @@
 Description: Tidal is a domain specific language for live coding pattern.
 
 library
-  if impl(ghc == 8.4.4)
-    cpp-options: -DTIDAL_SEMIGROUP
-
   ghc-options: -Wall
   hs-source-dirs:
                  src
@@ -47,9 +44,10 @@
                        Sound.Tidal.Utils
                        Sound.Tidal.Version
                        Sound.Tidal.EspGrid
-
+  other-modules: Sound.Tidal.MiniTidal.TH
+                 Sound.Tidal.MiniTidal.Token
   Build-depends:
-      base < 5
+      base >=4.8 && <5
     , containers < 0.7
     , colour < 2.4
     , hosc < 0.18
@@ -59,8 +57,9 @@
     , mwc-random < 0.15
     , vector < 0.13
     , bifunctors < 5.6
-    , transformers < 0.5.6
-    
+    , transformers < 0.5.7
+    , template-haskell >= 2.10.0.0 && < 3
+
   if !impl(ghc >= 8.4.1)
     build-depends: semigroups == 0.18.*
 
@@ -75,6 +74,7 @@
                  Sound.Tidal.MiniTidalTest
                  Sound.Tidal.ParseTest
                  Sound.Tidal.PatternTest
+                 Sound.Tidal.ScalesTest
                  Sound.Tidal.UITest
                  Sound.Tidal.UtilsTest
                  TestUtils
diff --git a/tidal.el b/tidal.el
--- a/tidal.el
+++ b/tidal.el
@@ -95,50 +95,50 @@
 import Sound.Tidal.Context
 tidal <- startMulti [superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}] (defaultConfig {cFrameTimespan = 1/20, cCtrlListen = True})
 let p = streamReplace tidal
-    hush = streamHush tidal
-    list = streamList tidal
-    mute = streamMute tidal
-    unmute = streamUnmute tidal
-    solo = streamSolo tidal
-    unsolo = streamUnsolo tidal
-    once = streamOnce tidal False
-    asap = streamOnce tidal True
-    nudgeAll = streamNudgeAll tidal
-    all = streamAll tidal
-    resetCycles = streamResetCycles tidal
-    setcps = asap . cps
-    xfade i = transition tidal (Sound.Tidal.Transition.xfadeIn 4) i
-    xfadeIn i t = transition tidal (Sound.Tidal.Transition.xfadeIn t) i
-    histpan i t = transition tidal (Sound.Tidal.Transition.histpan t) i
-    wait i t = transition tidal (Sound.Tidal.Transition.wait t) i
-    waitT i f t = transition tidal (Sound.Tidal.Transition.waitT f t) i
-    jump i = transition tidal (Sound.Tidal.Transition.jump) i
-    jumpIn i t = transition tidal (Sound.Tidal.Transition.jumpIn t) i
-    jumpIn' i t = transition tidal (Sound.Tidal.Transition.jumpIn' t) i
-    jumpMod i t = transition tidal (Sound.Tidal.Transition.jumpMod t) i
-    mortal i lifespan release = transition tidal (Sound.Tidal.Transition.mortal lifespan release) i
-    interpolate i = transition tidal (Sound.Tidal.Transition.interpolate) i
-    interpolateIn i t = transition tidal (Sound.Tidal.Transition.interpolateIn t) i
-    clutch i = transition tidal (Sound.Tidal.Transition.clutch) i
-    clutchIn i t = transition tidal (Sound.Tidal.Transition.clutchIn t) i
-    anticipate i = transition tidal (Sound.Tidal.Transition.anticipate) i
-    anticipateIn i t = transition tidal (Sound.Tidal.Transition.anticipateIn t) i
-    d1 = p 1
-    d2 = p 2 -- . (|< orbit 1)
-    d3 = p 3 -- . (|< orbit 2)
-    d4 = p 4 -- . (|< orbit 3)
-    d5 = p 5 -- . (|< orbit 4)
-    d6 = p 6 -- . (|< orbit 5)
-    d7 = p 7 -- . (|< orbit 6)
-    d8 = p 8 -- . (|< orbit 7)
-    d9 = p 9 -- . (|< orbit 8)
-    d10 = p 10
-    d11 = p 11
-    d12 = p 12
-    d13 = p 13
-    d14 = p 14
-    d15 = p 15
-    d16 = p 16
+let hush = streamHush tidal
+let list = streamList tidal
+let mute = streamMute tidal
+let unmute = streamUnmute tidal
+let solo = streamSolo tidal
+let unsolo = streamUnsolo tidal
+let once = streamOnce tidal False
+let asap = streamOnce tidal True
+let nudgeAll = streamNudgeAll tidal
+let all = streamAll tidal
+let resetCycles = streamResetCycles tidal
+let setcps = asap . cps
+let xfade i = transition tidal (Sound.Tidal.Transition.xfadeIn 4) i
+let xfadeIn i t = transition tidal (Sound.Tidal.Transition.xfadeIn t) i
+let histpan i t = transition tidal (Sound.Tidal.Transition.histpan t) i
+let wait i t = transition tidal (Sound.Tidal.Transition.wait t) i
+let waitT i f t = transition tidal (Sound.Tidal.Transition.waitT f t) i
+let jump i = transition tidal (Sound.Tidal.Transition.jump) i
+let jumpIn i t = transition tidal (Sound.Tidal.Transition.jumpIn t) i
+let jumpIn' i t = transition tidal (Sound.Tidal.Transition.jumpIn' t) i
+let jumpMod i t = transition tidal (Sound.Tidal.Transition.jumpMod t) i
+let mortal i lifespan release = transition tidal (Sound.Tidal.Transition.mortal lifespan release) i
+let interpolate i = transition tidal (Sound.Tidal.Transition.interpolate) i
+let interpolateIn i t = transition tidal (Sound.Tidal.Transition.interpolateIn t) i
+let clutch i = transition tidal (Sound.Tidal.Transition.clutch) i
+let clutchIn i t = transition tidal (Sound.Tidal.Transition.clutchIn t) i
+let anticipate i = transition tidal (Sound.Tidal.Transition.anticipate) i
+let anticipateIn i t = transition tidal (Sound.Tidal.Transition.anticipateIn t) i
+let d1 = p 1
+let d2 = p 2 . (|< orbit 1)
+let d3 = p 3 . (|< orbit 2)
+let d4 = p 4 . (|< orbit 3)
+let d5 = p 5 . (|< orbit 4)
+let d6 = p 6 . (|< orbit 5)
+let d7 = p 7 . (|< orbit 6)
+let d8 = p 8 . (|< orbit 7)
+let d9 = p 9 . (|< orbit 8)
+let d10 = p 10
+let d11 = p 11
+let d12 = p 12
+let d13 = p 13
+let d14 = p 14
+let d15 = p 15
+let d16 = p 16
   ")
   (tidal-send-string ":set prompt \"tidal> \"")
 )
