diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,102 @@
+# History of changes
+
+## MIDA 0.4.4
+
+* cosmetic corrections in source code;
+
+* switch to better libraries libraries.
+
+## MIDA 0.4.3
+
+* various corrections and cosmetic changes;
+
+* improved printing of syntax trees;
+
+* allow more flexible looping expressions.
+
+## MIDA 0.4.2
+
+* introduced simplifications on the level of internal language;
+
+* changed default values of some parameters;
+
+* some characters have been replaced with pretty Unicode symbols;
+
+* improved manual.
+
+## MIDA 0.4.1
+
+* dramatically improved efficiency, now very long compositions can be
+  quickly rendered;
+
+* lexer: changed style of comments, shell-like comments adopted;
+
+* changed alias of notes: dièse is written now as `s` not as `#`, so middle
+  octave is: `c5`, `cs5`, `d5`, `ds5`, `e5`, etc.;
+
+* now there are alias for all supported (in MIDI) pitches from 0 to 127,
+  that is: from `c0` to `g10` (alias `c10` -- `g10` added);
+
+* changed alias of modulation signs, reason for such change is purely
+  technical -- all alias now are predefined definitions, rather than
+  syntactic sugar, so all alias must be valid identifiers;
+
+* identifiers can contain underline sign (`_`);
+
+* arbitrary number of files can be specified for loading (from command line,
+  as well as from interactive REPL);
+
+* many purely technical changes that are difficult to explain concisely, but
+  they should be mentioned, most important being addition of test suite and
+  ability to generate source files from syntax trees;
+
+* added command line options: `--license` and `--version`.
+
+## MIDA 0.4.0
+
+* fixed bug in batch mode;
+
+* added tab completion based on contents of current input line, including
+  completion of file names for some commands;
+
+* detection and rejection of recursive definitions;
+
+* improved interface;
+
+* wholly refactored (and sometimes rewritten) code (it's finally
+  sufficiently elegant);
+
+* more intuitive logic of evaluation in some corner cases;
+
+* optional displaying of simplified principles (for debug and educational
+  purposes);
+
+* ability to set tempo and program for preview;
+
+* improved documentation.
+
+## MIDA 0.3.0
+
+* improved interface and parsing;
+
+* added `:prv` and `:load` special commands;
+
+* added additional parameters: modulation, breath, aftertouch, and pitch
+  bend;
+
+* fixed minor bugs.
+
+## MIDA 0.2.0
+
+* better command line experience: history, auto-completion and more;
+
+* fixed bug with infinite translation of scores that consist of elements
+  which have zero duration;
+
+* introduced conception of sections;
+
+* all operations have become fully polymorphic.
+
+## MIDA 0.1.0
+
+Initial release.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # MIDA
 
 [![License GPL 3](https://img.shields.io/badge/license-GPL_3-green.svg)](http://www.gnu.org/licenses/gpl-3.0.txt)
-
+[![Hackage](https://img.shields.io/hackage/v/mida.svg?style=flat)](https://hackage.haskell.org/package/mida)
 [![Build Status](https://travis-ci.org/mrkkrp/mida.svg?branch=master)](https://travis-ci.org/mrkkrp/mida)
 
 MIDA is a minimalistic declarative language for algorithmic generation of
@@ -29,7 +29,7 @@
 3. Download and untar git repository of MIDA, or clone it:
 
    ```
-   $ git clone https://github.com/mrkkrp/mida.git master
+   $ git clone https://github.com/mrkkrp/mida.git
    ```
 
 4. Go to the root directory of the repository and execute:
@@ -65,7 +65,7 @@
 
 See [MIDA Manual](https://mrkkrp.github.io/mida/) for more information.
 
-## How to control any parameter of any instrument / plugin?
+## How to control other things?
 
 If you're into this sort of thing, you may like my another project, called
 [ALGA](https://github.com/mrkkrp/alga). It allows to control automation in
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,6 @@
+module Main (main) where
+
 import Distribution.Simple
+
+main :: IO ()
 main = defaultMain
diff --git a/mida.cabal b/mida.cabal
--- a/mida.cabal
+++ b/mida.cabal
@@ -18,7 +18,7 @@
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
 name:                mida
-version:             0.4.3
+version:             0.4.4
 synopsis:            Language for algorithmic generation of MIDI files
 description:
 
@@ -51,7 +51,7 @@
 copyright:           Copyright © 2014, 2015 Mark Karpov
 category:            Language
 build-type:          Simple
-extra-source-files:  README.md
+extra-source-files:  README.md, CHANGELOG.md
 cabal-version:       >= 1.10
 
 library
@@ -61,11 +61,22 @@
   build-depends:     HCodecs                >= 0.5
                    , base                   >= 4.8 && < 5
                    , containers             >= 0.5.5.1
-                   , mersenne-random-pure64 >= 0.2.0.4
+                   , megaparsec             == 4.*
                    , mtl                    >= 2.1.3.1
-                   , parsec                 >= 3.1.8
+                   , random
                    , text                   >= 1.2.0.4
+                   , tf-random              >= 0.5
                    , transformers           >= 0.2.0.0 && < 0.5
+  default-extensions:
+                     BangPatterns
+                   , DeriveFoldable
+                   , DeriveFunctor
+                   , FlexibleInstances
+                   , GeneralizedNewtypeDeriving
+                   , OverloadedStrings
+                   , StandaloneDeriving
+                   , TupleSections
+                   , TypeSynonymInstances
   exposed-modules:   Mida.Configuration
                    , Mida.Language
                    , Mida.Language.Element
@@ -91,15 +102,26 @@
                    , directory              >= 1.2.1.0
                    , filepath               >= 1.3.0.2
                    , haskeline              >= 0.7.1.3
-                   , mersenne-random-pure64 >= 0.2.0.4
-                   , mida                   >= 0.4.2
+                   , megaparsec             == 4.*
+                   , mida                   >= 0.4.3
                    , mtl                    >= 2.1.3.1
                    , optparse-applicative   >= 0.11.0.2
-                   , parsec                 >= 3.1.8
                    , process                >= 1.2.0.0
+                   , random
                    , text                   >= 1.2.0.4
                    , text-format            >= 0.3.1.1
+                   , tf-random              >= 0.5
                    , transformers           >= 0.2.0.0 && < 0.5
+  default-extensions:
+                     BangPatterns
+                   , DeriveFoldable
+                   , DeriveFunctor
+                   , FlexibleInstances
+                   , GeneralizedNewtypeDeriving
+                   , OverloadedStrings
+                   , StandaloneDeriving
+                   , TupleSections
+                   , TypeSynonymInstances
   default-language:  Haskell2010
 
 test-suite tests
@@ -112,13 +134,14 @@
                    , QuickCheck                 >= 2.4 && < 3
                    , base                       >= 4.8 && < 5
                    , containers                 >= 0.5.5.1
-                   , mersenne-random-pure64     >= 0.2.0.4
-                   , mida                       >= 0.4.2
+                   , megaparsec                 == 4.*
+                   , mida                       >= 0.4.3
                    , mtl                        >= 2.1.3.1
-                   , parsec                     >= 3.1.8
+                   , random
                    , test-framework             >= 0.4 && < 1
                    , test-framework-quickcheck2 >= 0.3 && < 0.4
                    , text                       >= 1.2.0.4
+                   , tf-random                  >= 0.5
                    , transformers               >= 0.2.0.0 && < 0.5
 
 source-repository head
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -17,8 +17,6 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE OverloadedStrings #-}
-
 module Main (main) where
 
 import Control.Monad
@@ -34,69 +32,69 @@
 import Mida.Interaction
 
 data Opts = Opts
-    { opInterac :: Bool
-    , opSeed    :: Int
-    , opQuarter :: Int
-    , opBeats   :: Int
-    , opOutput  :: String
-    , opLicense :: Bool
-    , opVersion :: Bool
-    , opFiles   :: [String] }
+  { opInterac :: Bool
+  , opSeed    :: Int
+  , opQuarter :: Int
+  , opBeats   :: Int
+  , opOutput  :: String
+  , opLicense :: Bool
+  , opVersion :: Bool
+  , opFiles   :: [String] }
 
 main :: IO ()
 main = execParser opts >>= f
-    where f Opts { opLicense = True } = T.putStr license
-          f Opts { opVersion = True } = F.print "MIDA {}\n" (F.Only version)
-          f Opts { opFiles   = []   } = g $ interaction version
-          f Opts { opInterac = True
-                 , opFiles   = ns   } = g $ cmdLoad ns >> interaction version
-          f Opts { opSeed    = s
-                 , opQuarter = q
-                 , opBeats   = b
-                 , opOutput  = out
-                 , opFiles   = ns   } = g $ cmdLoad ns >> cmdMake s q b out
-          g x     = T.putStrLn notice >> runMida x
-          version = "0.4.3"
+  where f Opts { opLicense = True } = T.putStr license
+        f Opts { opVersion = True } = F.print "MIDA {}\n" (F.Only version)
+        f Opts { opFiles   = []   } = g $ interaction version
+        f Opts { opInterac = True
+               , opFiles   = ns   } = g $ cmdLoad ns >> interaction version
+        f Opts { opSeed    = s
+               , opQuarter = q
+               , opBeats   = b
+               , opOutput  = out
+               , opFiles   = ns   } = g $ cmdLoad ns >> cmdMake s q b out
+        g x     = T.putStrLn notice >> runMida x
+        version = "0.4.4"
 
 notice :: T.Text
 notice =
-    "MIDA Copyright © 2014, 2015 Mark Karpov\n\n\
-    \This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-    \and you are welcome to redistribute it under certain conditions; see\n\
-    \GNU General Public License for details.\n"
+  "MIDA Copyright © 2014, 2015 Mark Karpov\n\n\
+  \This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
+  \and you are welcome to redistribute it under certain conditions; see\n\
+  \GNU General Public License for details.\n"
 
 license :: T.Text
 license =
-    "MIDA — realization of MIDA, language for generation of MIDI files.\n\
-    \Copyright © 2014, 2015 Mark Karpov\n\
-    \\n\
-    \MIDA is free software: you can redistribute it and/or modify it under the\n\
-    \terms of the GNU General Public License as published by the Free Software\n\
-    \Foundation, either version 3 of the License, or (at your option) any\n\
-    \later version.\n\
-    \\n\
-    \MIDA is distributed in the hope that it will be useful, but WITHOUT ANY\n\
-    \WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n\
-    \FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\n\
-    \details.\n\
-    \\n\
-    \You should have received a copy of the GNU General Public License along\n\
-    \with this program. If not, see <http://www.gnu.org/licenses/>.\n"
+  "MIDA — realization of MIDA, language for generation of MIDI files.\n\
+  \Copyright © 2014, 2015 Mark Karpov\n\
+  \\n\
+  \MIDA is free software: you can redistribute it and/or modify it under the\n\
+  \terms of the GNU General Public License as published by the Free Software\n\
+  \Foundation, either version 3 of the License, or (at your option) any\n\
+  \later version.\n\
+  \\n\
+  \MIDA is distributed in the hope that it will be useful, but WITHOUT ANY\n\
+  \WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n\
+  \FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\n\
+  \details.\n\
+  \\n\
+  \You should have received a copy of the GNU General Public License along\n\
+  \with this program. If not, see <http://www.gnu.org/licenses/>.\n"
 
 runMida :: MidaIO () -> IO ()
 runMida e = do
   params <- loadConfig
   wdir   <- getCurrentDirectory
   void $ runMidaInt e
-       MidaSt { stPrevLen = lookupCfg params "prvlen" 18
-              , stSrcFile = lookupCfg params "src"    wdir </> "foo.da"
-              , stProg    = lookupCfg params "prog"   0
-              , stTempo   = lookupCfg params "tempo"  120 }
-       MidaCfg { cfgPrompt  = lookupCfg params "prompt"  "> "
-               , cfgVerbose = lookupCfg params "verbose" True
-               , cfgPrvCmd  = lookupCfg params "prvcmd"  "timidity"
-               , cfgProgOp  = lookupCfg params "progop"  "--force-program"
-               , cfgTempoOp = lookupCfg params "tempop"  "--adjust-tempo" }
+    MidaSt { stPrevLen = lookupCfg params "prvlen" 18
+           , stSrcFile = lookupCfg params "src"    wdir </> "foo.da"
+           , stProg    = lookupCfg params "prog"   0
+           , stTempo   = lookupCfg params "tempo"  120 }
+    MidaCfg { cfgPrompt  = lookupCfg params "prompt"  "> "
+            , cfgVerbose = lookupCfg params "verbose" True
+            , cfgPrvCmd  = lookupCfg params "prvcmd"  "timidity"
+            , cfgProgOp  = lookupCfg params "progop"  "--force-program"
+            , cfgTempoOp = lookupCfg params "tempop"  "--adjust-tempo" }
 
 loadConfig :: IO Params
 loadConfig = do
diff --git a/src/Mida/Configuration.hs b/src/Mida/Configuration.hs
--- a/src/Mida/Configuration.hs
+++ b/src/Mida/Configuration.hs
@@ -17,25 +17,21 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
 module Mida.Configuration
     ( Params
     , parseConfig
     , lookupCfg )
 where
 
-import Data.Char (isSpace)
-import Data.Functor.Identity
+import Control.Applicative
+import Control.Monad
 import Data.Maybe (fromMaybe, listToMaybe)
 import qualified Data.Map as M
 import qualified Data.Text.Lazy as T
 
-import Text.Parsec
-import Text.Parsec.Language
-import Text.Parsec.Text.Lazy
-import qualified Text.Parsec.Token as Token
+import Text.Megaparsec
+import Text.Megaparsec.Text.Lazy
+import qualified Text.Megaparsec.Lexer as L
 
 type Params = M.Map String String
 
@@ -53,52 +49,37 @@
     parseValue "false" = Just False
     parseValue _       = Nothing
 
+lookupCfg :: Parsable a => Params -> String -> a -> a
+lookupCfg cfg v d = fromMaybe d $ M.lookup v cfg >>= parseValue
+
+parseNum :: (Num a, Read a) => String -> Maybe a
+parseNum = fmap fst . listToMaybe . reads
+
 parseConfig :: String -> T.Text -> Either String Params
 parseConfig file = either (Left . show) Right . parse pConfig file
 
 pConfig :: Parser Params
-pConfig = M.fromList <$> (whiteSpace *> many pItem <* eof)
+pConfig = M.fromList <$> (sc *> many pItem <* eof)
 
 pItem :: Parser (String, String)
-pItem = (,) <$> identifier <* reservedOp "=" <*> (pString <|> pThing)
-
-pThing :: Parser String
-pThing = lexeme $ many (satisfy $ not . isSpace)
-
-lookupCfg :: Parsable a => Params -> String -> a -> a
-lookupCfg cfg v d = fromMaybe d $ M.lookup v cfg >>= parseValue
-
-lang :: GenLanguageDef T.Text () Identity
-lang = Token.LanguageDef
-       { Token.commentStart    = ""
-       , Token.commentEnd      = ""
-       , Token.commentLine     = "#"
-       , Token.nestedComments  = True
-       , Token.identStart      = letter <|> char '_'
-       , Token.identLetter     = alphaNum <|> char '_'
-       , Token.opStart         = Token.opLetter lang
-       , Token.opLetter        = oneOf "="
-       , Token.reservedNames   = ["true", "false"]
-       , Token.reservedOpNames = ["="]
-       , Token.caseSensitive   = True }
+pItem = (,) <$> pIdentifier <* pOperator "=" <*> (pString <|> pThing)
 
-lexer :: Token.GenTokenParser T.Text () Identity
-lexer = Token.makeTokenParser lang
+pIdentifier :: Parser String
+pIdentifier = lexeme $ (:) <$> first <*> many other
+  where first = letterChar   <|> char '_'
+        other = alphaNumChar <|> char '_'
 
-identifier :: Parser String
-identifier = Token.identifier lexer
+pOperator :: String -> Parser String
+pOperator = lexeme . string
 
 pString :: Parser String
-pString = Token.stringLiteral lexer
+pString = lexeme $ char '"' >> manyTill L.charLiteral (char '"')
 
-reservedOp :: String -> Parser ()
-reservedOp = Token.reservedOp lexer
+pThing :: Parser String
+pThing = lexeme $ some alphaNumChar
 
 lexeme :: Parser a -> Parser a
-lexeme = Token.lexeme lexer
-
-whiteSpace :: Parser ()
-whiteSpace = Token.whiteSpace lexer
+lexeme = L.lexeme sc
 
-parseNum :: (Num a, Read a) => String -> Maybe a
-parseNum = fmap fst . listToMaybe . reads
+sc :: Parser ()
+sc = L.space (void spaceChar) (L.skipLineComment "#") empty
diff --git a/src/Mida/Interaction.hs b/src/Mida/Interaction.hs
--- a/src/Mida/Interaction.hs
+++ b/src/Mida/Interaction.hs
@@ -18,8 +18,6 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE OverloadedStrings #-}
-
 module Mida.Interaction
     ( MidaIO
     , MidaInt
diff --git a/src/Mida/Language/Element.hs b/src/Mida/Language/Element.hs
--- a/src/Mida/Language/Element.hs
+++ b/src/Mida/Language/Element.hs
@@ -18,13 +18,10 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE DeriveFunctor  #-}
-{-# LANGUAGE DeriveFoldable #-}
-
 module Mida.Language.Element
-    ( Principle
-    , Elt
-    , Element (..) )
+  ( Principle
+  , Elt
+  , Element (..) )
 where
 
 import Control.Arrow ((***))
@@ -33,15 +30,15 @@
 type Elt       = Element Int
 
 data Element a
-    = Val  a
-    | Sec  [Element a]
-    | Mul  [Element a]
-    | CMul [([Element a], [Element a])]
-      deriving (Eq, Show, Functor, Foldable)
+  = Val  a
+  | Sec  [Element a]
+  | Mul  [Element a]
+  | CMul [([Element a], [Element a])]
+    deriving (Eq, Show, Functor, Foldable)
 
 instance Applicative Element where
-    pure           = Val
-    (Val  f) <*> x = f <$> x
-    (Sec  f) <*> x = Sec  $ (<*> x) <$> f
-    (Mul  f) <*> x = Mul  $ (<*> x) <$> f
-    (CMul f) <*> x = CMul $ (((<*> x) <$>) *** ((<*> x) <$>)) <$> f
+  pure           = Val
+  (Val  f) <*> x = f <$> x
+  (Sec  f) <*> x = Sec  $ (<*> x) <$> f
+  (Mul  f) <*> x = Mul  $ (<*> x) <$> f
+  (CMul f) <*> x = CMul $ (((<*> x) <$>) *** ((<*> x) <$>)) <$> f
diff --git a/src/Mida/Language/Environment.hs b/src/Mida/Language/Environment.hs
--- a/src/Mida/Language/Environment.hs
+++ b/src/Mida/Language/Environment.hs
@@ -18,65 +18,63 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE TupleSections              #-}
-
 module Mida.Language.Environment
-    ( MidaEnv (..)
-    , runMidaEnv
-    , addDef
-    , remDef
-    , clearDefs
-    , getPrin
-    , getSrc
-    , fullSrc
-    , getRefs
-    , purgeEnv
-    , checkRecur
-    , setRandGen
-    , newRandGen )
+  ( MidaEnv (..)
+  , runMidaEnv
+  , addDef
+  , remDef
+  , clearDefs
+  , getPrin
+  , getSrc
+  , fullSrc
+  , getRefs
+  , purgeEnv
+  , checkRecur
+  , setRandGen
+  , newRandGen )
 where
 
 import Control.Arrow ((***), (>>>))
 import Control.Monad.State.Strict
 import Data.Maybe (fromMaybe)
 import Data.Monoid ((<>))
+import System.Random (split)
 import qualified Data.Map.Strict as M
 import qualified Data.Text.Lazy as T
 
-import System.Random.Mersenne.Pure64
+import System.Random.TF (TFGen, mkTFGen)
 
 import Mida.Language.SyntaxTree
 import Mida.Representation.Base (noteAlias, modifiers)
 import Mida.Representation.Show (showDefinition)
 
 data MidaEnvSt = MidaEnvSt
-    { stDefs    :: Defs
-    , stRandGen :: PureMT }
+  { stDefs    :: Defs
+  , stRandGen :: TFGen }
 
 type Defs = M.Map String SyntaxTree
 
 newtype MidaEnv m a = MidaEnv
-    { unMidaEnv :: StateT MidaEnvSt m a }
-    deriving ( Functor
-             , Applicative
-             , Monad
-             , MonadState MidaEnvSt
-             , MonadTrans
-             , MonadIO )
+  { unMidaEnv :: StateT MidaEnvSt m a }
+  deriving ( Functor
+           , Applicative
+           , Monad
+           , MonadState MidaEnvSt
+           , MonadTrans
+           , MonadIO )
 
 runMidaEnv :: Monad m => MidaEnv m a -> m a
 runMidaEnv e = evalStateT (unMidaEnv e) MidaEnvSt
                { stDefs    = defaultDefs
-               , stRandGen = pureMT 0 }
+               , stRandGen = mkTFGen 0 }
 
 defaultDefs :: Defs
 defaultDefs = M.fromList $ zip noteAlias (f <$> [0..])
-              <> zip modifiers (f <$> [128,256..])
-    where f = return . Value
+            <> zip modifiers (f <$> [128,256..])
+  where f = return . Value
 
 getDefs :: Monad m => MidaEnv m Defs
-getDefs = stDefs <$> get
+getDefs = gets stDefs
 
 setDefs :: Monad m => Defs -> MidaEnv m ()
 setDefs x = modify $ \e -> e { stDefs = x }
@@ -104,39 +102,39 @@
 
 tDefs :: String -> Defs -> [String]
 tDefs name defs = maybe mzero cm $ name `M.lookup` defs
-    where cm               = (>>= f)
-          f (Value      _) = mempty
-          f (Section    x) = cm x
-          f (Multi      x) = cm x
-          f (CMulti     x) = x >>= (cm *** cm >>> uncurry (<>))
-          f (Reference  x) = return x <> tDefs x defs
-          f (Range    _ _) = mempty
-          f (Product  x y) = f x <> f y
-          f (Division x y) = f x <> f y
-          f (Sum      x y) = f x <> f y
-          f (Diff     x y) = f x <> f y
-          f (Loop     x y) = f x <> f y
-          f (Rotation x y) = f x <> f y
-          f (Reverse    x) = f x
+  where cm               = (>>= f)
+        f (Value      _) = mempty
+        f (Section    x) = cm x
+        f (Multi      x) = cm x
+        f (CMulti     x) = x >>= (cm *** cm >>> uncurry (<>))
+        f (Reference  x) = return x <> tDefs x defs
+        f (Range    _ _) = mempty
+        f (Product  x y) = f x <> f y
+        f (Division x y) = f x <> f y
+        f (Sum      x y) = f x <> f y
+        f (Diff     x y) = f x <> f y
+        f (Loop     x y) = f x <> f y
+        f (Rotation x y) = f x <> f y
+        f (Reverse    x) = f x
 
 purgeEnv :: Monad m => [String] -> MidaEnv m ()
 purgeEnv tops = f <$> getDefs >>= setDefs
-    where f defs = M.intersection defs $ M.unions [ts, ms defs, defaultDefs]
-          ms     = M.unions . fmap toDefs . zipWith tDefs tops . repeat
-          ts     = toDefs tops
+  where f defs = M.intersection defs $ M.unions [ts, ms defs, defaultDefs]
+        ms     = M.unions . fmap toDefs . zipWith tDefs tops . repeat
+        ts     = toDefs tops
 
 checkRecur :: Monad m => String -> SyntaxTree -> MidaEnv m Bool
 checkRecur name tree = check <$> getDefs
-    where check = elem name . tDefs name . M.insert name tree
+  where check = elem name . tDefs name . M.insert name tree
 
 setRandGen :: Monad m => Int -> MidaEnv m ()
-setRandGen x = modify $ \e -> e { stRandGen = pureMT (fromIntegral x) }
+setRandGen x = modify $ \e -> e { stRandGen = mkTFGen x }
 
-newRandGen :: Monad m => MidaEnv m PureMT
+newRandGen :: Monad m => MidaEnv m TFGen
 newRandGen = do
-  (n, g) <- (randomWord64 . stRandGen) <$> get
-  modify $ \e -> e { stRandGen = pureMT n }
-  return . pureMT . fst . randomWord64 $ g
+  (g, g') <- split <$> gets stRandGen
+  modify $ \e -> e { stRandGen = g' }
+  return g
 
 toDefs :: [String] -> Defs
 toDefs = M.fromList . fmap (, [])
diff --git a/src/Mida/Language/Eval.hs b/src/Mida/Language/Eval.hs
--- a/src/Mida/Language/Eval.hs
+++ b/src/Mida/Language/Eval.hs
@@ -19,12 +19,10 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
 module Mida.Language.Eval
-    ( evalDef
-    , eval
-    , toPrin )
+  ( evalDef
+  , eval
+  , toPrin )
 where
 
 import Control.Arrow ((***))
@@ -32,41 +30,42 @@
 import Data.List (tails)
 import Data.Maybe (listToMaybe)
 import Data.Monoid ((<>))
+import System.Random (next)
 
-import System.Random.Mersenne.Pure64
+import System.Random.TF (TFGen)
 
 import Mida.Language.SyntaxTree
 import Mida.Language.Element
 import Mida.Language.Environment
 
 data CalcSt = CalcSt
-    { clcHistory :: [Int]
-    , clcRandGen :: PureMT }
+  { clcHistory :: [Int]
+  , clcRandGen :: TFGen }
 
 newtype Calc a = Calc
-    { unCalc :: State CalcSt a }
-    deriving ( Functor
-             , Applicative
-             , Monad
-             , MonadState CalcSt )
+  { unCalc :: State CalcSt a }
+  deriving ( Functor
+           , Applicative
+           , Monad
+           , MonadState CalcSt )
 
 evalDef :: Monad m => String -> MidaEnv m [Int]
 evalDef name = getPrin name >>= eval
 
 eval :: Monad m => SyntaxTree -> MidaEnv m [Int]
 eval tree = liftM2 runCalc (resolve . cycle' <$> toPrin tree) newRandGen
-    where cycle' p = if null $ foldMap (:[]) (Sec p) then [] else cycle p
+  where cycle' p = if null $ foldMap (:[]) (Sec p) then [] else cycle p
 
 resolve :: Principle -> Calc [Int]
 resolve [] = return []
 resolve xs = concat <$> mapM f xs
-    where f (Val  x) = addHistory x >> return [x]
-          f (Sec  x) = resolve x
-          f (Mul  x) = choice x >>= maybe (return []) f
-          f (CMul x) = listToMaybe <$> filterM (matchHistory . fst) x >>=
-                       maybe (f . toMul $ x) (f . Mul . snd)
+  where f (Val  x) = addHistory x >> return [x]
+        f (Sec  x) = resolve x
+        f (Mul  x) = choice x >>= maybe (return []) f
+        f (CMul x) = listToMaybe <$> filterM (matchHistory . fst) x >>=
+                     maybe (f . toMul $ x) (f . Mul . snd)
 
-runCalc :: Calc a -> PureMT -> a
+runCalc :: Calc a -> TFGen -> a
 runCalc clc gen = evalState (unCalc clc)
                   CalcSt { clcHistory = mempty
                          , clcRandGen = gen }
@@ -74,7 +73,7 @@
 choice :: [a] -> Calc (Maybe a)
 choice [] = return Nothing
 choice xs = do
-  (n, g) <- randomInt . clcRandGen <$> get
+  (n, g) <- next <$> gets clcRandGen
   modify $ \c -> c { clcRandGen = g }
   return . Just $ xs !! (abs n `rem` length xs)
 
@@ -90,7 +89,7 @@
 
 matchHistory :: [Elt] -> Calc Bool
 matchHistory x = do
-  hs <- clcHistory <$> get
+  hs <- gets clcHistory
   return . or $ condMatch hs <$> x
 
 addHistory :: Int -> Calc ()
@@ -101,8 +100,8 @@
 
 simplifySec :: Principle -> Principle
 simplifySec = (>>= f)
-    where f (Sec xs) = simplifySec xs
-          f x        = simplifyElt x
+  where f (Sec xs) = simplifySec xs
+        f x        = simplifyElt x
 
 simplify :: Principle -> Principle
 simplify = (>>= simplifyElt)
@@ -118,26 +117,26 @@
 
 toPrin' :: Monad m => SyntaxTree -> MidaEnv m Principle
 toPrin' = fmap concat . mapM f
-    where
-      fPair (c, x)     = (,) <$> toPrin' c <*> toPrin' x
-      f (Value      x) = return . Val <$> return x
-      f (Section   xs) = return . Sec <$> toPrin' xs
-      f (Multi     xs) = return . Mul <$> toPrin' xs
-      f (CMulti    xs) = return . CMul <$> mapM fPair xs
-      f (Reference  x) = getPrin x >>= toPrin'
-      f (Range    x y) = return $ Val <$> if x > y then [x,x-1..y] else [x..y]
-      f (Product  x y) = adb (\a b -> [(*) <$> a <*> b]) <$> f x <*> f y
-      f (Division x y) = adb (\a b -> [sdiv <$> a <*> b]) <$> f x <*> f y
-      f (Sum      x y) = adb (\a b -> [(+) <$> a <*> b]) <$> f x <*> f y
-      f (Diff     x y) = adb (\a b -> [sdif <$> a <*> b]) <$> f x <*> f y
-      f (Loop     x y) = adb loop <$> f x <*> f y
-      f (Rotation x y) = adb (\a b -> [rotate a b]) <$> f x <*> f y
-      f (Reverse    x) = adu reverse' <$> f x
-      adb _ [] _       = []
-      adb _ xs []      = xs
-      adb g xs (y:ys)  = init xs ++ g (last xs) y ++ ys
-      adu _ []         = []
-      adu g (x:xs)     = g x : xs
+  where
+    fPair (c, x)     = (,) <$> toPrin' c <*> toPrin' x
+    f (Value      x) = return . Val <$> return x
+    f (Section   xs) = return . Sec <$> toPrin' xs
+    f (Multi     xs) = return . Mul <$> toPrin' xs
+    f (CMulti    xs) = return . CMul <$> mapM fPair xs
+    f (Reference  x) = getPrin x >>= toPrin'
+    f (Range    x y) = return $ Val <$> if x > y then [x,x-1..y] else [x..y]
+    f (Product  x y) = adb (\a b -> [(*) <$> a <*> b]) <$> f x <*> f y
+    f (Division x y) = adb (\a b -> [sdiv <$> a <*> b]) <$> f x <*> f y
+    f (Sum      x y) = adb (\a b -> [(+) <$> a <*> b]) <$> f x <*> f y
+    f (Diff     x y) = adb (\a b -> [sdif <$> a <*> b]) <$> f x <*> f y
+    f (Loop     x y) = adb loop <$> f x <*> f y
+    f (Rotation x y) = adb (\a b -> [rotate a b]) <$> f x <*> f y
+    f (Reverse    x) = adu reverse' <$> f x
+    adb _ [] _       = []
+    adb _ xs []      = xs
+    adb g xs (y:ys)  = init xs ++ g (last xs) y ++ ys
+    adu _ []         = []
+    adu g (x:xs)     = g x : xs
 
 sdiv :: Int -> Int -> Int
 sdiv x 0 = x
@@ -145,8 +144,8 @@
 
 sdif :: Int -> Int -> Int
 sdif x y
-    | x < y     = 0
-    | otherwise = x - y
+  | x < y     = 0
+  | otherwise = x - y
 
 loop :: Elt -> Elt -> Principle
 loop x       (Val y) = replicate y x
diff --git a/src/Mida/Language/SyntaxTree.hs b/src/Mida/Language/SyntaxTree.hs
--- a/src/Mida/Language/SyntaxTree.hs
+++ b/src/Mida/Language/SyntaxTree.hs
@@ -18,24 +18,24 @@
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
 module Mida.Language.SyntaxTree
-    ( SyntaxTree
-    , Sel (..) )
+  ( SyntaxTree
+  , Sel (..) )
 where
 
 type SyntaxTree = [Sel]
 
 data Sel -- syntactic element
-    = Value     Int
-    | Section   [Sel]
-    | Multi     [Sel]
-    | CMulti    [([Sel], [Sel])]
-    | Reference String
-    | Range     Int Int
-    | Product   Sel Sel
-    | Division  Sel Sel
-    | Sum       Sel Sel
-    | Diff      Sel Sel
-    | Loop      Sel Sel
-    | Rotation  Sel Sel
-    | Reverse   Sel
-      deriving (Eq, Show)
+  = Value     Int
+  | Section   [Sel]
+  | Multi     [Sel]
+  | CMulti    [([Sel], [Sel])]
+  | Reference String
+  | Range     Int Int
+  | Product   Sel Sel
+  | Division  Sel Sel
+  | Sum       Sel Sel
+  | Diff      Sel Sel
+  | Loop      Sel Sel
+  | Rotation  Sel Sel
+  | Reverse   Sel
+    deriving (Eq, Show)
diff --git a/src/Mida/Midi.hs b/src/Mida/Midi.hs
--- a/src/Mida/Midi.hs
+++ b/src/Mida/Midi.hs
@@ -17,8 +17,6 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE BangPatterns #-}
-
 module Mida.Midi
     ( genMidi
     , topDefs )
diff --git a/src/Mida/Representation/Base.hs b/src/Mida/Representation/Base.hs
--- a/src/Mida/Representation/Base.hs
+++ b/src/Mida/Representation/Base.hs
@@ -18,24 +18,24 @@
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
 module Mida.Representation.Base
-    ( noteAlias
-    , commentLine
-    , productOp
-    , divisionOp
-    , sumOp
-    , diffOp
-    , loopOp
-    , rotationOp
-    , reverseOp
-    , rangeOp
-    , defOp
-    , modifiers )
+  ( noteAlias
+  , commentLine
+  , productOp
+  , divisionOp
+  , sumOp
+  , diffOp
+  , loopOp
+  , rotationOp
+  , reverseOp
+  , rangeOp
+  , defOp
+  , modifiers )
 where
 
 noteAlias :: [String]
 noteAlias = zipWith f names ([0..127] :: [Int])
-    where names = cycle ["c","cs","d","ds","e","f","fs","g","gs","a","as","b"]
-          f n i = n ++ show (i `div` 12)
+  where names = cycle ["c","cs","d","ds","e","f","fs","g","gs","a","as","b"]
+        f n i = n ++ show (i `div` 12)
 
 commentLine :: String
 commentLine = "#"
diff --git a/src/Mida/Representation/Parser.hs b/src/Mida/Representation/Parser.hs
--- a/src/Mida/Representation/Parser.hs
+++ b/src/Mida/Representation/Parser.hs
@@ -18,78 +18,81 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE OverloadedStrings #-}
-
 module Mida.Representation.Parser
-    ( Statement (..)
-    , probeMida
-    , parseMida )
+  ( Statement (..)
+  , probeMida
+  , parseMida )
 where
 
+import Control.Applicative
 import Control.Monad (void)
-import Data.Functor.Identity
-import Data.List (nub)
 import qualified Data.Text.Lazy as T
 
-import Text.Parsec
-import Text.Parsec.Expr
-import Text.Parsec.Language
-import Text.Parsec.Text.Lazy
-import qualified Text.Parsec.Token as Token
+import Text.Megaparsec
+import Text.Megaparsec.Expr
+import Text.Megaparsec.Text.Lazy
+import qualified Text.Megaparsec.Lexer as L
 
 import Mida.Language.SyntaxTree (SyntaxTree, Sel (..))
 import qualified Mida.Representation.Base as B
 
 data Statement
-    = Definition String SyntaxTree
-    | Exposition SyntaxTree
-      deriving (Eq, Show)
+  = Definition String SyntaxTree
+  | Exposition SyntaxTree
+    deriving (Eq, Show)
 
 probeMida :: T.Text -> Bool
 probeMida txt = not $ or ["," `T.isSuffixOf` stripped
-                         , f ("[", "]")
-                         , f ("{", "}")
-                         , f ("<", ">")
-                         , f ("(", ")") ]
-    where stripped = T.strip txt
-          f (x, y) = (&&) <$> (> 0) <*> (/= g y) $ g x
-          g x      = T.count x stripped
+                       , f ("[", "]")
+                       , f ("{", "}")
+                       , f ("<", ">")
+                       , f ("(", ")") ]
+  where stripped = T.strip txt
+        f (x, y) = (&&) <$> (> 0) <*> (/= g y) $ g x
+        g x      = T.count x stripped
 
 parseMida :: String -> T.Text -> Either String [Statement]
 parseMida file txt =
-    case parse parser file txt of
-      Right x -> if null x
-                 then Left $ '\"' : file ++ "\":\ninvalid definition syntax"
-                 else Right x
-      Left  x -> Left . show $ x
-    where parser = if T.pack B.defOp `T.isInfixOf` txt
-                   then pSource
-                   else return <$> pExposition
+  case parse parser file txt of
+    Right x -> if null x
+               then Left $ '\"' : file ++ "\":\ninvalid definition syntax"
+               else Right x
+    Left  x -> Left . show $ x
+  where parser = if T.pack B.defOp `T.isInfixOf` txt
+                 then pSource
+                 else return <$> pExposition
 
 pSource :: Parser [Statement]
-pSource = whiteSpace *> many pDefinition <* eof
+pSource = sc *> many pDefinition <* eof
 
 pDefinition :: Parser Statement
-pDefinition = Definition <$> identifier <* reservedOp B.defOp <*> pPrinciple
+pDefinition = Definition <$> pIdentifier <* pOperator B.defOp <*> pPrinciple
 
 pExposition :: Parser Statement
-pExposition = Exposition <$> (whiteSpace *> pPrinciple <* eof)
+pExposition = Exposition <$> (sc *> pPrinciple <* eof)
 
+pIdentifier :: Parser String
+pIdentifier = lexeme $ (:) <$> first <*> many other
+  where first = letterChar   <|> char '_'
+        other = alphaNumChar <|> char '_'
+
+pOperator :: String -> Parser String
+pOperator = lexeme . string
+
 pPrinciple :: Parser SyntaxTree
 pPrinciple = sepBy (pExpression <|> pElement) (optional comma)
 
 pElement :: Parser Sel
-pElement
-    =  try pRange
-   <|> pValue
-   <|> try pReference
-   <|> pSection
-   <|> try pMulti
-   <|> pCMulti
-   <?> "element"
+pElement =  try pRange
+        <|> pValue
+        <|> try pReference
+        <|> pSection
+        <|> try pMulti
+        <|> pCMulti
+        <?> "element"
 
 pRange :: Parser Sel
-pRange = Range <$> pNatural <* reservedOp B.rangeOp <*> pNatural
+pRange = Range <$> pNatural <* pOperator B.rangeOp <*> pNatural
 
 pValue :: Parser Sel
 pValue = Value <$> pNatural
@@ -98,7 +101,7 @@
 pNatural = fromIntegral <$> natural <?> "literal value"
 
 pReference :: Parser Sel
-pReference = Reference <$> identifier <* notFollowedBy (reservedOp B.defOp)
+pReference = Reference <$> pIdentifier <* notFollowedBy (pOperator B.defOp)
 
 pSection :: Parser Sel
 pSection = Section <$> brackets pPrinciple
@@ -110,71 +113,41 @@
 pCMulti = CMulti <$> braces (many $ (,) <$> angles pPrinciple <*> pPrinciple)
 
 pExpression :: Parser Sel
-pExpression = buildExpressionParser optTable (parens pExpression <|> pElement)
-              <?> "expression"
+pExpression = makeExprParser (parens pExpression <|> pElement) optTable
 
-optTable :: [[Operator T.Text () Identity Sel]]
+optTable :: [[Operator Parser Sel]]
 optTable =
-    [[ Prefix (reservedOp B.reverseOp *> pure Reverse ) ]
-     , [ Infix (reservedOp B.productOp  *> pure Product ) AssocLeft
-       , Infix (reservedOp B.divisionOp *> pure Division) AssocLeft
-       , Infix (reservedOp B.sumOp      *> pure Sum     ) AssocLeft
-       , Infix (reservedOp B.diffOp     *> pure Diff    ) AssocLeft
-       , Infix (reservedOp B.loopOp     *> pure Loop    ) AssocLeft
-       , Infix (reservedOp B.rotationOp *> pure Rotation) AssocLeft ]]
-
-lang :: GenLanguageDef T.Text () Identity
-lang = Token.LanguageDef
-       { Token.commentStart    = ""
-       , Token.commentEnd      = ""
-       , Token.commentLine     = B.commentLine
-       , Token.nestedComments  = True
-       , Token.identStart      = letter   <|> char '_'
-       , Token.identLetter     = alphaNum <|> char '_'
-       , Token.opStart         = Token.opLetter lang
-       , Token.opLetter        = oneOf . nub . concat $ langOps
-       , Token.reservedOpNames = langOps
-       , Token.reservedNames   = []
-       , Token.caseSensitive   = True }
-
-langOps :: [String]
-langOps =
-    [ B.productOp
-    , B.divisionOp
-    , B.sumOp
-    , B.diffOp
-    , B.loopOp
-    , B.rotationOp
-    , B.reverseOp
-    , B.rangeOp
-    , B.defOp ]
-
-lexer :: Token.GenTokenParser T.Text () Identity
-lexer = Token.makeTokenParser lang
+    [[ Prefix (pOperator B.reverseOp *> pure Reverse ) ]
+     , [ InfixL (pOperator B.productOp  *> pure Product )
+       , InfixL (pOperator B.divisionOp *> pure Division)
+       , InfixL (pOperator B.sumOp      *> pure Sum     )
+       , InfixL (pOperator B.diffOp     *> pure Diff    )
+       , InfixL (pOperator B.loopOp     *> pure Loop    )
+       , InfixL (pOperator B.rotationOp *> pure Rotation) ]]
 
 angles :: Parser a -> Parser a
-angles = Token.angles lexer
+angles = between (symbol "<") (symbol ">")
 
 braces :: Parser a -> Parser a
-braces = Token.braces lexer
+braces = between (symbol "{") (symbol "}")
 
 brackets :: Parser a -> Parser a
-brackets = Token.brackets lexer
+brackets = between (symbol "[") (symbol "]")
 
 comma :: Parser ()
-comma = void $ Token.comma lexer
-
-identifier :: Parser String
-identifier = Token.identifier lexer
+comma = void $ symbol ","
 
 natural :: Parser Integer
-natural = Token.natural lexer
+natural = lexeme L.integer
 
 parens :: Parser a -> Parser a
-parens = Token.parens lexer
+parens = between (symbol "(") (symbol ")")
 
-reservedOp :: String -> Parser ()
-reservedOp = Token.reservedOp lexer
+symbol :: String -> Parser String
+symbol = L.symbol sc
 
-whiteSpace :: Parser ()
-whiteSpace = Token.whiteSpace lexer
+lexeme :: Parser a -> Parser a
+lexeme = L.lexeme sc
+
+sc :: Parser ()
+sc = L.space (void spaceChar) (L.skipLineComment "#") empty
diff --git a/src/Mida/Representation/Show.hs b/src/Mida/Representation/Show.hs
--- a/src/Mida/Representation/Show.hs
+++ b/src/Mida/Representation/Show.hs
@@ -18,8 +18,6 @@
 -- You should have received a copy of the GNU General Public License along
 -- with this program. If not, see <http://www.gnu.org/licenses/>.
 
-{-# LANGUAGE OverloadedStrings #-}
-
 module Mida.Representation.Show
     ( showStatement
     , showDefinition
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -38,63 +38,63 @@
 
 import Mida.Language (Sel (..))
 import Mida.Representation
-    ( Statement (..)
-    , probeMida
-    , parseMida
-    , showStatement )
+  ( Statement (..)
+  , probeMida
+  , parseMida
+  , showStatement )
 
 main :: IO ()
 main = defaultMain tests
 
 tests :: [Test]
 tests =
-    [ testGroup "Printer and Parser"
-      [ testProperty "Valid MIDA Probe"               prop_valid_probe
-      , testProperty "Printer and Parser Consistency" prop_pp_consistency ] ]
+  [ testGroup "Printer and Parser"
+    [ testProperty "Valid MIDA Probe"               prop_valid_probe
+    , testProperty "Printer and Parser Consistency" prop_pp_consistency ] ]
 
 prop_valid_probe :: Statement -> Bool
 prop_valid_probe = probeMida . showStatement
 
 prop_pp_consistency :: Statement -> Bool
 prop_pp_consistency = id &&& (parseMida "" . showStatement) >>> check
-    where check (x, Right [y]) = x == y
-          check _              = False
+  where check (x, Right [y]) = x == y
+        check _              = False
 
 instance Arbitrary Statement where
-    arbitrary =
-        oneof [ Definition <$> alphaNumIdentifier <*> arbitrary
-              , Exposition <$> arbitrary ]
+  arbitrary =
+    oneof [ Definition <$> identifier <*> arbitrary
+          , Exposition <$> arbitrary ]
 
 instance Arbitrary Sel where
-    arbitrary = sized arbitrarySel
+  arbitrary = sized arbitrarySel
 
 arbitrarySel :: Int -> Gen Sel
 arbitrarySel 0 =
-    oneof [ Value     <$> positive
-          , Reference <$> alphaNumIdentifier
-          , Range     <$> positive <*> positive ]
-    where positive = arbitrary `suchThat` (>= 0)
+  oneof [ Value     <$> nonNegative
+        , Reference <$> identifier
+        , Range     <$> nonNegative <*> nonNegative ]
+  where nonNegative = getNonNegative <$> arbitrary
 arbitrarySel n =
-    oneof [ Section  <$> listSel
-          , Multi    <$> listSel
-          , CMulti   <$> listCnd
-          , Product  <$> leafSel <*> leafSel
-          , Division <$> leafSel <*> leafSel
-          , Sum      <$> leafSel <*> leafSel
-          , Diff     <$> leafSel <*> leafSel
-          , Loop     <$> leafSel <*> leafSel
-          , Rotation <$> leafSel <*> leafSel
-          , Reverse  <$> leafSel ]
-    where cnSel d = arbitrarySel (n `div` d)
-          vcSel d = arbitrarySizedIntegral `suchThat` (>= 0)
-                    >>= \s -> vectorOf s (cnSel $ d * s)
-          leafSel = cnSel 2
-          listSel = vcSel 1
-          listCnd = arbitrarySizedIntegral `suchThat` (>= 1)
-                    >>= \s -> vectorOf s $ (,) <$> vcSel s <*> vcSel s
+  oneof [ Section  <$> listSel
+        , Multi    <$> listSel
+        , CMulti   <$> listCnd
+        , Product  <$> leafSel <*> leafSel
+        , Division <$> leafSel <*> leafSel
+        , Sum      <$> leafSel <*> leafSel
+        , Diff     <$> leafSel <*> leafSel
+        , Loop     <$> leafSel <*> leafSel
+        , Rotation <$> leafSel <*> leafSel
+        , Reverse  <$> leafSel ]
+  where cnSel d = arbitrarySel (n `div` d)
+        vcSel d = (getNonNegative <$> arbitrary)
+                  >>= \s -> vectorOf s (cnSel $ d * s)
+        leafSel = cnSel 2
+        listSel = vcSel 1
+        listCnd = (getPositive <$> arbitrary)
+                  >>= \s -> vectorOf s $ (,) <$> vcSel s <*> vcSel s
 
-alphaNumIdentifier :: Gen String
-alphaNumIdentifier = (:) <$> ch0 <*> chN
-    where ch0 = arbitrary `suchThat` underscoreOr isLetter
-          chN = arbitrary `suchThat` all (underscoreOr isAlphaNum)
-          underscoreOr f x = x == '_' || f x
+identifier :: Gen String
+identifier = (:) <$> ch0 <*> chN
+  where ch0 = u isLetter
+        chN = listOf $ u isAlphaNum
+        u f = frequency [(1, return '_'), (74, arbitrary `suchThat` f)]
