packages feed

mida 1.0.1 → 1.0.2

raw patch · 16 files changed

+194/−191 lines, 16 filesdep +file-embeddep +hspecdep +semigroupsdep −test-frameworkdep −test-framework-quickcheck2dep ~HCodecsdep ~QuickCheckdep ~aeson

Dependencies added: file-embed, hspec, semigroups

Dependencies removed: test-framework, test-framework-quickcheck2

Dependency ranges changed: HCodecs, QuickCheck, aeson, base, containers, data-default, exceptions, filepath, formatting, haskeline, megaparsec, mida, mtl, optparse-applicative, path, path-io, process, text, tf-random, transformers, yaml

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+## MIDA 1.0.2++* Refactoring, switch to Hspec for testing and Megaparsec 5.+ ## MIDA 1.0.1  * Fixed issues with `directory` package. Please use `directory-1.2.3.0` or
+ license.txt view
@@ -0,0 +1,16 @@+MIDA — realization of MIDA, language for generation of MIDI files.++Copyright © 2014–2016 Mark Karpov++MIDA is free software: you can redistribute it and/or modify it under the+terms of the GNU General Public License as published by the Free Software+Foundation, either version 3 of the License, or (at your option) any+later version.++MIDA is distributed in the hope that it will be useful, but WITHOUT ANY+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more+details.++You should have received a copy of the GNU General Public License along+with this program. If not, see <http://www.gnu.org/licenses/>.
mida.cabal view
@@ -17,7 +17,8 @@ -- with this program. If not, see <http://www.gnu.org/licenses/>.  name:                 mida-version:              1.0.1+version:              1.0.2+cabal-version:        >= 1.10 synopsis:             Language for algorithmic generation of MIDI files description: @@ -50,8 +51,10 @@ copyright:            Copyright © 2014–2016 Mark Karpov category:             Language build-type:           Simple-extra-source-files:   README.md, CHANGELOG.md-cabal-version:        >= 1.10+data-files:           notice.txt+                    , license.txt+extra-doc-files:      CHANGELOG.md+                    , README.md  flag dev   description:        Turn on development settings.@@ -64,18 +67,20 @@     ghc-options:      -O2 -Wall -Werror   else     ghc-options:      -O2 -Wall-  ghc-prof-options:   -O2 -Wall -prof -fprof-cafs -rtsopts-  build-depends:      HCodecs                >= 0.5-                    , base                   >= 4.8 && < 5-                    , containers             >= 0.5.5.1-                    , exceptions             >= 0.8-                    , haskeline              >= 0.7.1.3-                    , megaparsec             >= 4.2-                    , mtl                    >= 2.1.3.1+  build-depends:      HCodecs                >= 0.5     && < 0.6+                    , QuickCheck             >= 2.8.2   && < 3.0+                    , base                   >= 4.8     && < 5.0+                    , containers             >= 0.5.5.1 && < 0.6+                    , exceptions             >= 0.8     && < 0.9+                    , haskeline              >= 0.7.1.3 && < 0.8+                    , megaparsec             >= 5.0     && < 6.0+                    , mtl                    >= 2.1.3.1 && < 3.0                     , random-                    , text                   >= 1.2.0.4-                    , tf-random              >= 0.5-                    , transformers           >= 0.2.0.0+                    , text                   >= 1.2.0.4 && < 1.3+                    , tf-random              >= 0.5     && < 1.0+                    , transformers           >= 0.2.0.0 && < 0.6+  if !impl(ghc >= 8.0)+    build-depends:    semigroups             == 0.18.*   default-extensions: FlexibleContexts                     , FlexibleInstances                     , OverloadedStrings@@ -95,33 +100,35 @@ executable mida   main-is:            Main.hs   hs-source-dirs:     src-  other-modules:      Mida.Interaction   if flag(dev)     ghc-options:      -O2 -Wall -Werror   else     ghc-options:      -O2 -Wall-  ghc-prof-options:   -O2 -Wall -prof -fprof-cafs -rtsopts-  build-depends:      HCodecs                >= 0.5-                    , aeson                  >= 0.7-                    , base                   >= 4.8 && < 5-                    , containers             >= 0.5.5.1-                    , data-default           >= 0.5.3-                    , exceptions             >= 0.8-                    , filepath               >= 1.3.0.2-                    , formatting             >= 6.2-                    , haskeline              >= 0.7.1.3-                    , megaparsec             >= 4.2-                    , mida                   >= 1.0.1-                    , mtl                    >= 2.1.3.1-                    , optparse-applicative   >= 0.11.0.2-                    , path                   >= 0.5.3-                    , path-io                >= 0.3.1-                    , process                >= 1.2.0.0+  build-depends:      HCodecs                >= 0.5     && < 0.6+                    , QuickCheck             >= 2.8.2   && < 3.0+                    , aeson                  >= 0.7     && < 0.12+                    , base                   >= 4.8     && < 5.0+                    , containers             >= 0.5.5.1 && < 0.6+                    , data-default           >= 0.5.3   && < 0.8+                    , exceptions             >= 0.8     && < 0.9+                    , file-embed             >= 0.0.9+                    , filepath               >= 1.3.0.2 && < 1.5+                    , formatting             >= 6.2     && < 7.0+                    , haskeline              >= 0.7.1.3 && < 0.8+                    , megaparsec             >= 5.0     && < 6.0+                    , mida                   >= 1.0.2+                    , mtl                    >= 2.1.3.1 && < 3.0+                    , optparse-applicative   >= 0.11.0.2 && < 0.13+                    , path                   >= 0.5.3   && < 0.6+                    , path-io                >= 0.3.1   && < 2.0+                    , process                >= 1.2     && < 1.5                     , random-                    , text                   >= 1.2.0.4-                    , tf-random              >= 0.5-                    , transformers           >= 0.2.0.0-                    , yaml                   >= 0.8.15.1+                    , text                   >= 1.2.0.4 && < 1.3+                    , tf-random              >= 0.5     && < 1.0+                    , transformers           >= 0.2.0.0 && < 0.6+                    , yaml                   >= 0.8.15  && < 0.9+  if !impl(ghc >= 8.0)+    build-depends:    semigroups             == 0.18.*   default-extensions: FlexibleContexts                     , FlexibleInstances                     , OverloadedStrings@@ -153,20 +160,19 @@   else     ghc-options:      -O2 -Wall   default-language:   Haskell2010-  build-depends:      HCodecs                    >= 0.5-                    , QuickCheck                 >= 2.4 && < 3-                    , base                       >= 4.8 && < 5-                    , containers                 >= 0.5.5.1-                    , megaparsec                 >= 4.2-                    , mida                       >= 1.0.1-                    , mtl                        >= 2.1.3.1+  build-depends:      HCodecs                >= 0.5     && < 0.6+                    , QuickCheck             >= 2.8.2   && < 3.0+                    , base                   >= 4.8     && < 5.0+                    , containers             >= 0.5.5.1 && < 0.6+                    , hspec                  >= 2.0     && < 3.0+                    , megaparsec             >= 5.0     && < 6.0+                    , mida                   >= 1.0.2+                    , mtl                    >= 2.1.3.1 && < 3.0                     , 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+                    , text                   >= 1.2.0.4 && < 1.3+                    , tf-random              >= 0.5     && < 1.0+                    , transformers           >= 0.2.0.0 && < 0.6  source-repository head   type:               git-  location:           git://github.com/mrkkrp/mida.git+  location:           https://github.com/mrkkrp/mida.git
+ notice.txt view
@@ -0,0 +1,5 @@+MIDA Copyright © 2014–2016 Mark Karpov++This program comes with ABSOLUTELY NO WARRANTY. This is free software,+and you are welcome to redistribute it under certain conditions; see+GNU General Public License for details.
src/Main.hs view
@@ -16,10 +16,13 @@ -- 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 TemplateHaskell #-}+ module Main (main) where  import Control.Monad import Control.Monad.IO.Class+import Data.FileEmbed import Data.Text.Lazy (Text) import Data.Version (showVersion) import Formatting@@ -64,31 +67,12 @@ -- | Shortish copyright notice.  notice :: Text-notice =-  "MIDA Copyright © 2014–2016 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"+notice = $(embedStringFile "notice.txt")  -- | Longer copyright notice.  license :: Text-license =-  "MIDA — realization of MIDA, language for generation of MIDI files.\n\-  \Copyright © 2014–2016 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"+license = $(embedStringFile "license.txt")  -- | Read configuration file if present and run MIDA monad. 
src/Mida/Interaction.hs view
@@ -90,7 +90,7 @@   file <- gets stSrcFile   case parseMida (fromAbsFile file) expr of     Right x -> mapM_ f x-    Left  x -> liftIO $ fprint (string % "\n") x+    Left  x -> liftIO (putStr x)     where f (Definition n t) = processDef n t           f (Exposition   t) = do             len     <- gets stPrevLen
src/Mida/Interaction/Commands.hs view
@@ -50,11 +50,11 @@   , createProcess   , waitForProcess   , delegate_ctlc )-import qualified Codec.Midi as Midi-import qualified Data.Text.Lazy as T-import qualified Data.Text.Lazy.IO as T+import qualified Codec.Midi               as Midi+import qualified Data.Text.Lazy           as T+import qualified Data.Text.Lazy.IO        as T import qualified System.Console.Haskeline as L-import qualified System.FilePath as FP+import qualified System.FilePath          as FP  -- | Description of REPL command. 
src/Mida/Language.hs view
@@ -19,6 +19,7 @@ module Mida.Language   ( SyntaxTree   , Sel     (..)+  , Statement (..)   , Principle   , Element (..)   , MidaEnv@@ -38,7 +39,7 @@   , toPrin ) where -import Mida.Language.SyntaxTree (SyntaxTree, Sel (..))+import Mida.Language.SyntaxTree (SyntaxTree, Sel (..), Statement (..)) import Mida.Language.Element (Principle, Element (..)) import Mida.Language.Environment import Mida.Language.Eval (evalDef, eval, toPrin)
src/Mida/Language/Element.hs view
@@ -26,6 +26,7 @@ where  import Control.Arrow ((***))+import Data.List.NonEmpty (NonEmpty (..)) import Numeric.Natural  -- | Collection of elements for evaluation, representation of some aspect of@@ -39,7 +40,7 @@   = Val  a             -- ^ Single value, evaluates to itself   | Sec  [Element a]   -- ^ Universal container for other values   | Mul  [Element a]   -- ^ Multivalue, the way to introduce varying elements-  | CMul [([Element a], [Element a])] -- ^ Conditional multivalue+  | CMul (NonEmpty ([Element a], [Element a])) -- ^ Conditional multivalue     deriving (Eq, Show, Functor, Foldable)  instance Applicative Element where
src/Mida/Language/Environment.hs view
@@ -48,10 +48,11 @@ import Mida.Representation.Base (noteAlias, modifiers) import Mida.Representation.Show (showDefinition) import Numeric.Natural-import System.Console.Haskeline.MonadException -- FIXME+import System.Console.Haskeline.MonadException import System.Random (split) import System.Random.TF (TFGen, mkTFGen)-import qualified Data.Map.Strict as M+import qualified Data.List.NonEmpty as NE+import qualified Data.Map.Strict    as M  -- | MIDA environment state. Basically this amounts to collection of -- definitions and random number generator.@@ -184,7 +185,7 @@         f (Value      _) = mempty         f (Section    x) = cm x         f (Multi      x) = cm x-        f (CMulti     x) = x >>= (cm *** cm >>> uncurry (<>))+        f (CMulti     x) = NE.toList x >>= (cm *** cm >>> uncurry (<>))         f (Reference  x) = return x <> tDefs x defs         f (Range    _ _) = mempty         f (Product  x y) = f x <> f y
src/Mida/Language/Eval.hs view
@@ -29,6 +29,7 @@ import Control.Monad.State.Class import Control.Monad.State.Lazy import Data.List (tails)+import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe (listToMaybe) import Data.Monoid ((<>)) import Mida.Language.Element@@ -37,6 +38,7 @@ import Numeric.Natural import System.Random (next) import System.Random.TF (TFGen)+import qualified Data.List.NonEmpty as NE  -- | State record used for calculation\/evaluation of principles. @@ -70,8 +72,8 @@   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)+        f (CMul x) = listToMaybe <$> filterM (matchHistory . fst) (NE.toList x)+          >>= maybe (f . toMul $ x) (f . Mul . snd)  -- | Run lazy state monad with 'CalcSt' state. @@ -112,9 +114,9 @@ -- | Convert internals of conditional multivalue into plain multivalue.  toMul-  :: [([Element Natural], [Element Natural])] -- ^ Pattern\/result pairs+  :: NonEmpty ([Element Natural], [Element Natural]) -- ^ Pattern\/result pairs   -> Element Natural   -- ^ Internals of plain multivalue-toMul xs = Mul (xs >>= snd)+toMul xs = Mul (NE.toList xs >>= snd)  -- | A monadic wrapper around 'condMatch'. @@ -155,13 +157,13 @@ -- several elements after simplification.  simplifyElt :: Element Natural -> Principle-simplifyElt x@(Val _)        = [x]-simplifyElt (Sec  [x])       = simplify [x]-simplifyElt (Mul  [x])       = simplify [x]-simplifyElt (CMul [(_, xs)]) = simplifyElt (Mul xs)-simplifyElt (Sec  xs)        = [Sec (simplifySec xs)]-simplifyElt (Mul  xs)        = [Mul (simplify xs)]-simplifyElt (CMul xs)        = [CMul ((simplify *** simplify) <$> xs)]+simplifyElt x@(Val _)  = [x]+simplifyElt (Sec  [x]) = simplify [x]+simplifyElt (Mul  [x]) = simplify [x]+simplifyElt (CMul ((_, xs):|[])) = simplifyElt (Mul xs)+simplifyElt (Sec  xs)  = [Sec (simplifySec xs)]+simplifyElt (Mul  xs)  = [Mul (simplify xs)]+simplifyElt (CMul xs)  = [CMul ((simplify *** simplify) <$> xs)]  -- | The meat of the algorithm that transforms 'SyntaxTree' into 'Principle'. 
src/Mida/Language/SyntaxTree.hs view
@@ -18,16 +18,20 @@  module Mida.Language.SyntaxTree   ( SyntaxTree-  , Sel (..) )+  , Sel (..)+  , Statement (..) ) where +import Data.Char (isLetter, isAlphaNum)+import Data.List.NonEmpty (NonEmpty (..)) import Numeric.Natural+import Test.QuickCheck  -- | Syntax tree in our case is just a collection of syntactic elements.  type SyntaxTree = [Sel] --- | Syntactic element corresponds to language features. Some of them have+-- | Syntactic element corresponds to language tokens. Some of them have -- direct corresponding constructor in 'Mida.Language.Element.Element', -- others have to be simplified first. @@ -35,7 +39,7 @@   = Value     Natural  -- ^ Literal value   | Section   [Sel]    -- ^ Section   | Multi     [Sel]    -- ^ Multivalue-  | CMulti    [([Sel], [Sel])] -- ^ Conditional multivalue+  | CMulti    (NonEmpty ([Sel], [Sel])) -- ^ Conditional multivalue   | Reference String   -- ^ Reference (name of variable)   | Range     Natural Natural -- ^ Range of values   | Product   Sel Sel  -- ^ Product of principles@@ -46,3 +50,53 @@   | Rotation  Sel Sel  -- ^ Rotation   | Reverse   Sel      -- ^ Reversed principle     deriving (Eq, Show)++instance Arbitrary Sel where+  arbitrary = sized arbitrarySel++arbitrarySel :: Int -> Gen Sel+arbitrarySel 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 = listOf (cnSel $ d * 20)+        leafSel = cnSel 10+        listSel = vcSel 20+        listCnd =+          let x = (,) <$> vcSel 25 <*> vcSel 25+          in (:|) <$> x <*> listOf x++-- | Statement can be either definition or exposition. Expositions are only+-- used in REPL.++data Statement+  = Definition String SyntaxTree+  | Exposition SyntaxTree+    deriving (Eq, Show)++instance Arbitrary Statement where+  arbitrary =+    oneof [ Definition <$> identifier <*> arbitrary+          , Exposition <$> arbitrary ]++----------------------------------------------------------------------------+-- Helpers++identifier :: Gen String+identifier = (:) <$> ch0 <*> chN+  where ch0 = u isLetter+        chN = listOf $ u isAlphaNum+        u f = frequency [(1, return '_'), (74, arbitrary `suchThat` f)]
src/Mida/Representation.hs view
@@ -18,8 +18,7 @@ -- with this program. If not, see <http://www.gnu.org/licenses/>.  module Mida.Representation-  ( Statement (..)-  , probeMida+  ( probeMida   , parseMida   , showStatement   , showSyntaxTree
src/Mida/Representation/Parser.hs view
@@ -18,30 +18,22 @@ -- with this program. If not, see <http://www.gnu.org/licenses/>.  module Mida.Representation.Parser-  ( Statement (..)-  , probeMida+  ( probeMida   , parseMida ) where  import Control.Applicative (empty) import Control.Monad (void) import Data.Text.Lazy (Text)-import Mida.Language.SyntaxTree (SyntaxTree, Sel (..))+import Mida.Language.SyntaxTree import Numeric.Natural import Text.Megaparsec import Text.Megaparsec.Expr import Text.Megaparsec.Text.Lazy-import qualified Data.Text.Lazy as T+import qualified Data.List.NonEmpty       as NE+import qualified Data.Text.Lazy           as T import qualified Mida.Representation.Base as B-import qualified Text.Megaparsec.Lexer as L---- | Statement can be either definition or exposition. Expositions are only--- used in REPL.--data Statement-  = Definition String SyntaxTree-  | Exposition SyntaxTree-    deriving (Eq, Show)+import qualified Text.Megaparsec.Lexer    as L  -- | Test if given fragment of MIDA code is finished and self-contained. @@ -67,7 +59,7 @@     Right x -> if null x       then Left ('\"' : file ++ "\":\ninvalid definition syntax")       else Right x-    Left  e -> Left (show e)+    Left  e -> Left (parseErrorPretty e)   where parser = if T.pack B.defOp `T.isInfixOf` txt          then pSource          else pure <$> pExposition@@ -121,7 +113,8 @@ pMulti = Multi <$> braces pPrinciple  pCMulti :: Parser Sel-pCMulti = CMulti <$> braces (many $ (,) <$> angles pPrinciple <*> pPrinciple)+pCMulti = CMulti . NE.fromList <$>+  braces (some $ (,) <$> angles pPrinciple <*> pPrinciple)  pExpression :: Parser Sel pExpression = makeExprParser (parens pExpression <|> pElement) optTable
src/Mida/Representation/Show.hs view
@@ -30,10 +30,10 @@ import Data.Text.Lazy (Text) import Mida.Language.Element import Mida.Language.SyntaxTree-import Mida.Representation.Parser (Statement (..))-import qualified Data.Text.Lazy.Builder as T (Builder, fromString, toLazyText)+import qualified Data.List.NonEmpty         as NE+import qualified Data.Text.Lazy.Builder     as T (Builder, fromString, toLazyText) import qualified Data.Text.Lazy.Builder.Int as T (decimal)-import qualified Mida.Representation.Base as B+import qualified Mida.Representation.Base   as B  -- | Render a statement. This handles definitions and expositions. @@ -86,7 +86,7 @@     f (Value       x) = T.decimal x     f (Section     x) = "[" <> cm f x <> "]"     f (Multi       x) = "{" <> cm f x <> "}"-    f (CMulti      x) = "{" <> cm (c *** cm f >>> uncurry (<>)) x <> "}"+    f (CMulti      x) = "{" <> cm (c *** cm f >>> uncurry (<>)) (NE.toList x) <> "}"     f (Reference   x) = T.fromString x     f (Range     x y) = T.decimal x <> T.fromString B.rangeOp <> T.decimal y     f (Product   x y) = f x <> pad B.productOp   <> p y
tests/Main.hs view
@@ -1,5 +1,5 @@ ----- QuickCheck tests for MIDA.+-- Test suite of MIDA. -- -- Copyright © 2014–2016 Mark Karpov --@@ -16,84 +16,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/>. -{--  TODO:-  - parser for configuration files;-  - translation from syntax tree to internal language;-  - process of translation Principle -> [Int];-  - generation of MIDI files.--}--{-# OPTIONS -fno-warn-orphans #-}- module Main (main) where -import Control.Arrow ((&&&), (>>>))-import Data.Char (isLetter, isAlphaNum)--import Test.Framework (defaultMain, testGroup, Test)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck--import Mida.Language (Sel (..)) import Mida.Representation-  ( Statement (..)-  , probeMida-  , parseMida-  , showStatement )+import Test.Hspec+import Test.QuickCheck  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 ] ]--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--instance Arbitrary Statement where-  arbitrary =-    oneof [ Definition <$> identifier <*> arbitrary-          , Exposition <$> arbitrary ]--instance Arbitrary Sel where-  arbitrary = sized arbitrarySel--arbitrarySel :: Int -> Gen Sel-arbitrarySel 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 = (getNonNegative <$> arbitrary)-                  >>= \s -> vectorOf s (cnSel $ d * s)-        leafSel = cnSel 2-        listSel = vcSel 1-        listCnd = (getPositive <$> arbitrary)-                  >>= \s -> vectorOf s $ (,) <$> vcSel s <*> vcSel s+main = hspec spec -identifier :: Gen String-identifier = (:) <$> ch0 <*> chN-  where ch0 = u isLetter-        chN = listOf $ u isAlphaNum-        u f = frequency [(1, return '_'), (74, arbitrary `suchThat` f)]+spec :: Spec+spec = do+  describe "probeMida" $+    it "returns True for every correct statement" $+      property (probeMida . showStatement)+  describe "parser and printer" $+    it "printed representation of statement can be parsed back" $+      property $ \stmt ->+        parseMida "" (showStatement stmt) `shouldBe` Right [stmt]