-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Haskell Music Theory Base -- -- Haskell music theory Base Library @package hmt-base @version 0.20 -- | Cell references & indexing. module Music.Theory.Array.Cell_Ref -- | A indexed case-insensitive column references. The column -- following Z is AA. newtype Column_Ref Column_Ref :: String -> Column_Ref [column_ref_string] :: Column_Ref -> String -- | Inclusive range of column references. type Column_Range = (Column_Ref, Column_Ref) -- | 1-indexed row reference. type Row_Ref = Int -- | Zero index of Row_Ref. row_index :: Row_Ref -> Int -- | Inclusive range of row references. type Row_Range = (Row_Ref, Row_Ref) -- | Cell reference, column then row. type Cell_Ref = (Column_Ref, Row_Ref) -- | Inclusive range of cell references. type Cell_Range = (Cell_Ref, Cell_Ref) -- | Case folding letter to index function. Only valid for ASCII letters. -- --
-- map letter_index ['A' .. 'Z'] == [0 .. 25] -- map letter_index ['a','d' .. 'm'] == [0,3 .. 12] --letter_index :: Char -> Int -- | Inverse of letter_index. -- --
-- map index_letter [0,3 .. 12] == ['A','D' .. 'M'] --index_letter :: Int -> Char -- | Translate column reference to 0-index. -- --
-- :set -XOverloadedStrings -- map column_index ["A","c","z","ac","XYZ"] == [0,2,25,28,17575] --column_index :: Column_Ref -> Int -- | Column reference to interior index within specified range. Type -- specialised index. -- --
-- map (Data.Ix.index ('A','Z')) ['A','C','Z'] == [0,2,25]
-- map (interior_column_index ("A","Z")) ["A","C","Z"] == [0,2,25]
--
--
--
-- map (Data.Ix.index ('B','C')) ['B','C'] == [0,1]
-- map (interior_column_index ("B","C")) ["B","C"] == [0,1]
--
interior_column_index :: Column_Range -> Column_Ref -> Int
-- | Inverse of column_index.
--
-- -- let c = ["A","Z","AA","AZ","BA","BZ","CA"] -- map column_ref [0,25,26,51,52,77,78] == c ---- --
-- column_ref (0+25+1+25+1+25+1) == "CA" --column_ref :: Int -> Column_Ref -- | Type specialised pred. -- --
-- column_ref_pred "DF" == "DE" --column_ref_pred :: Column_Ref -> Column_Ref -- | Type specialised succ. -- --
-- column_ref_succ "DE" == "DF" --column_ref_succ :: Column_Ref -> Column_Ref -- | Bimap of column_index. -- --
-- column_indices ("b","p") == (1,15)
-- column_indices ("B","IT") == (1,253)
--
column_indices :: Column_Range -> (Int, Int)
-- | Type specialised range.
--
--
-- column_range ("L","R") == ["L","M","N","O","P","Q","R"]
-- Data.Ix.range ('L','R') == "LMNOPQR"
--
column_range :: Column_Range -> [Column_Ref]
-- | Type specialised inRange.
--
--
-- map (column_in_range ("L","R")) ["A","N","Z"] == [False,True,False]
-- map (column_in_range ("L","R")) ["L","N","R"] == [True,True,True]
--
--
--
-- map (Data.Ix.inRange ('L','R')) ['A','N','Z'] == [False,True,False]
-- map (Data.Ix.inRange ('L','R')) ['L','N','R'] == [True,True,True]
--
column_in_range :: Column_Range -> Column_Ref -> Bool
-- | Type specialised rangeSize.
--
--
-- map column_range_size [("A","Z"),("AA","ZZ")] == [26,26 * 26]
-- Data.Ix.rangeSize ('A','Z') == 26
--
column_range_size :: Column_Range -> Int
-- | Type specialised range.
row_range :: Row_Range -> [Row_Ref]
-- | The standard uppermost leftmost cell reference, A1.
--
-- -- Just cell_ref_minima == parse_cell_ref "A1" --cell_ref_minima :: Cell_Ref -- | Cell reference parser for standard notation of (column,row). -- --
-- parse_cell_ref "CC348" == Just ("CC",348)
--
parse_cell_ref :: String -> Maybe Cell_Ref
-- | isJust of parse_cell_ref.
is_cell_ref :: String -> Bool
-- | fromJust of parse_cell_ref
parse_cell_ref_err :: String -> Cell_Ref
-- | Cell reference pretty printer.
--
--
-- cell_ref_pp ("CC",348) == "CC348"
--
cell_ref_pp :: Cell_Ref -> String
-- | Translate cell reference to 0-indexed pair.
--
--
-- cell_index ("CC",348) == (80,347)
-- Data.Ix.index ((Column_Ref "AA",1),(Column_Ref "ZZ",999)) (Column_Ref "CC",348) == 54293
--
cell_index :: Cell_Ref -> (Int, Int)
-- | Inverse of cell_index.
--
-- -- index_to_cell (80,347) == (Column_Ref "CC",348) -- index_to_cell (4,5) == (Column_Ref "E",6) --index_to_cell :: (Int, Int) -> Cell_Ref -- | cell_index of parse_cell_ref_err parse_cell_index :: String -> (Int, Int) -- | Type specialised range, cells are in column-order. -- --
-- cell_range (("AA",1),("AC",1)) == [("AA",1),("AB",1),("AC",1)]
--
--
--
-- let r = [("AA",1),("AA",2),("AB",1),("AB",2),("AC",1),("AC",2)]
-- cell_range (("AA",1),("AC",2)) == r
--
--
--
-- Data.Ix.range (('A',1),('C',1)) == [('A',1),('B',1),('C',1)]
--
--
--
-- let r = [('A',1),('A',2),('B',1),('B',2),('C',1),('C',2)]
-- Data.Ix.range (('A',1),('C',2)) == r
--
cell_range :: Cell_Range -> [Cell_Ref]
-- | Variant of cell_range in row-order.
--
--
-- let r = [("AA",1),("AB",1),("AC",1),("AA",2),("AB",2),("AC",2)]
-- cell_range_row_order (("AA",1),("AC",2)) == r
--
cell_range_row_order :: Cell_Range -> [Cell_Ref]
instance GHC.Read.Read Music.Theory.Array.Cell_Ref.Column_Ref
instance GHC.Show.Show Music.Theory.Array.Cell_Ref.Column_Ref
instance GHC.Classes.Eq Music.Theory.Array.Cell_Ref.Column_Ref
instance GHC.Classes.Ord Music.Theory.Array.Cell_Ref.Column_Ref
instance GHC.Enum.Enum Music.Theory.Array.Cell_Ref.Column_Ref
instance GHC.Ix.Ix Music.Theory.Array.Cell_Ref.Column_Ref
-- | Bits functions.
module Music.Theory.Bits
-- | True = 1, False = 0
bit_pp :: Bool -> Char
-- | map bit_pp
bits_pp :: [Bool] -> String
-- | Generate n place bit sequence for x.
gen_bitseq :: FiniteBits b => Int -> b -> [Bool]
-- | Given bit sequence (most to least significant) generate Bits
-- value.
--
-- -- :set -XBinaryLiterals -- pack_bitseq [True,False,True,False] == 0b1010 -- pack_bitseq [True,False,False,True,False,False] == 0b100100 -- 0b100100 == 36 --pack_bitseq :: Bits i => [Bool] -> i -- | bits_pp of gen_bitseq. -- --
-- :set -XBinaryLiterals -- 0xF0 == 0b11110000 -- gen_bitseq_pp 8 (0xF0::Int) == "11110000" --gen_bitseq_pp :: FiniteBits b => Int -> b -> String -- | Boolean functions. module Music.Theory.Bool -- | If-then-else as a function. -- --
-- ifThenElse True "true" "false" == "true" --ifThenElse :: Bool -> a -> a -> a -- | Case analysis as a function. Find first key that is True else -- elseValue. -- --
-- caseElse "z" [(True,"x"),(False,"y")] == "x" -- caseElse "z" [(False,"x"),(False,"y")] == "z" --caseElse :: t -> [(Bool, t)] -> t -- | Case-of analysis as a function. Find first key that compares equal to -- selectValue else elseValue. -- --
-- caseOfElse "z" 'b' [('a',"x"),('b',"y")] == "y"
--
caseOfElse :: Eq k => v -> k -> [(k, v)] -> v
module Music.Theory.Concurrent
-- | Pause current thread for the indicated duration (in seconds), see
-- pauseThreadLimit.
threadDelaySeconds :: RealFrac n => n -> IO ()
-- | The number of seconds that threadDelaySeconds can wait for.
-- Values larger than this require a different thread delay mechanism,
-- see threadSleepForSeconds. The value is the number of
-- microseconds in maxBound::Int. For 64-bit architectures this
-- is not likely to be an issue, however for 32-bit it can be.
--
-- -- round ((2 ** 31) / (60 * 60) / 1e6) == 1 -- hours -- round ((2 ** 63) / (60 * 60 * 24 * 365 * 100) / 1e6) == 2925 -- years --threadDelaySecondsLimit :: Fractional n => n -- | Sleep current thread for the indicated duration (in seconds). Divides -- long sleeps into parts smaller than threadSleepForSeconds. threadSleepForSeconds :: RealFrac n => n -> IO () -- | Directory functions using find system utility. module Music.Theory.Directory.Find -- | Find files having indicated filename. This runs the system utility -- find, so is Unix only. -- --
-- dir_find "DX7-ROM1A.syx" "/home/rohan/sw/hsc3-data/data/yamaha/" --dir_find :: FilePath -> FilePath -> IO [FilePath] -- | Require that exactly one file is located, else error. -- --
-- dir_find_1 "DX7-ROM1A.syx" "/home/rohan/sw/hsc3-data/data/yamaha/" --dir_find_1 :: FilePath -> FilePath -> IO FilePath -- | Recursively find files having case-insensitive filename extension. -- This runs the system utility find, so is Unix only. -- --
-- dir_find_ext ".syx" "/home/rohan/sw/hsc3-data/data/yamaha/" --dir_find_ext :: String -> FilePath -> IO [FilePath] -- | Post-process dir_find_ext to delete starting directory. -- --
-- dir_find_ext_rel ".syx" "/home/rohan/sw/hsc3-data/data/yamaha/" --dir_find_ext_rel :: String -> FilePath -> IO [FilePath] -- | Scan each directory on path recursively for file. Stop once a file is -- located. Runs dir_find so is Unix only. -- --
-- path_scan_recursively ["/home/rohan/sw/hmt-base"] "Directory.hs" --path_scan_recursively :: [FilePath] -> FilePath -> IO (Maybe FilePath) -- | Search each directory on path recursively for file. Runs -- dir_find so is Unix only. -- --
-- path_search_recursively ["/home/rohan/sw"] "README.md" --path_search_recursively :: [FilePath] -> FilePath -> IO [FilePath] -- | Either module Music.Theory.Either -- | Maybe Left of Either. from_left :: Either a b -> Maybe a -- | fromJust of from_left from_left_err :: Either t e -> t -- | Maybe Right of Either. from_right :: Either x t -> Maybe t -- | fromJust of from_right from_right_err :: Either e t -> t -- | Flip from right to left, ie. either Right Left either_swap :: Either a b -> Either b a -- | Variant of rights that preserves first Left. -- --
-- all_right (map Right [1..3]) == Right [1..3] -- all_right [Right 1,Left 'a',Left 'b'] == Left 'a' --all_right :: [Either a b] -> Either a [b] -- | Lower Either to Maybe by discarding Left. either_to_maybe :: Either a b -> Maybe b -- | Data.Either.isLeft, which however hugs doesn't know of. is_left :: Either a b -> Bool -- | Data.Either.isRight, which however hugs doesn't know of. is_right :: Either a b -> Bool -- | Data.Either.partitionEithers, which however hugs doesn't know of. partition_eithers :: [Either a b] -> ([a], [b]) -- | Enumeration functions. module Music.Theory.Enum -- | Generic variant of fromEnum (p.263). genericFromEnum :: (Integral i, Enum e) => e -> i -- | Generic variant of toEnum (p.263). genericToEnum :: (Integral i, Enum e) => i -> e -- | Variant of enumFromTo that, if p is after q, -- cycles from maxBound to minBound. -- --
-- import Data.Word -- enum_from_to_cyclic (254 :: Word8) 1 == [254,255,0,1] --enum_from_to_cyclic :: (Bounded a, Enum a) => a -> a -> [a] -- | Variant of enumFromTo that, if p is after q, -- enumerates from q to p. -- --
-- enum_from_to_reverse 5 1 == [5,4,3,2,1] -- enum_from_to_reverse 1 5 == enumFromTo 1 5 --enum_from_to_reverse :: Enum a => a -> a -> [a] -- | All elements in sequence. -- --
-- (enum_univ :: [Data.Word.Word8]) == [0 .. 255] --enum_univ :: (Bounded t, Enum t) => [t] -- | List of Enum values not in sorted input list. -- --
-- enum_list_gaps "abdh" == "cefg" --enum_list_gaps :: (Enum t, Eq t) => [t] -> [t] -- | enum_list_gaps of sort enum_set_gaps :: (Enum t, Eq t, Ord t) => [t] -> [t] -- | Data.Function related functions. module Music.Theory.Function -- | Unary operator. type UOp t = t -> t -- | Binary operator. type BinOp t = t -> t -> t -- | Iterate the function f n times, the inital value is -- x. -- --
-- recur_n 5 (* 2) 1 == 32 -- take (5 + 1) (iterate (* 2) 1) == [1,2,4,8,16,32] --recur_n :: Integral n => n -> (t -> t) -> t -> t -- | const of const. -- --
-- const2 5 undefined undefined == 5 -- const (const 5) undefined undefined == 5 --const2 :: a -> b -> c -> a -- | && of predicates, ie. do predicates f and -- g both hold at x. predicate_and :: (t -> Bool) -> (t -> Bool) -> t -> Bool -- | List variant of predicate_and, ie. foldr1 -- --
-- let r = [False,False,True,False,True,False] -- map (predicate_all [(> 0),(< 5),even]) [0..5] == r --predicate_all :: [t -> Bool] -> t -> Bool -- | || of predicates. predicate_or :: (t -> Bool) -> (t -> Bool) -> t -> Bool -- | any of predicates, ie. logical or of list of predicates. -- --
-- let r = [True,False,True,False,True,True] -- map (predicate_any [(== 0),(== 5),even]) [0..5] == r --predicate_any :: [t -> Bool] -> t -> Bool -- | == on. eq_on :: Eq t => (u -> t) -> u -> u -> Bool -- | fmap . fmap, ie. (t -> c) -> (a -> b -- -> t) -> a -> b -> c. fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) -- | fmap of fmap2, ie. (t -> d) -> (a -> b -> c -> t) -- -> a -> b -> c -> d. fmap3 :: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b)) -- | fmap of fmap3. fmap4 :: (Functor f, Functor g, Functor h, Functor i) => (a -> b) -> f (g (h (i a))) -> f (g (h (i b))) -- | fmap of fmap4 fmap5 :: (Functor f, Functor g, Functor h, Functor i, Functor j) => (a -> b) -> f (g (h (i (j a)))) -> f (g (h (i (j b)))) -- | fmap of fmap5 fmap6 :: (Functor f, Functor g, Functor h, Functor i, Functor j, Functor k) => (a -> b) -> f (g (h (i (j (k a))))) -> f (g (h (i (j (k b))))) -- | Operator name for fmap2. (.:) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) infixr 8 .: -- | Operator name for fmap3. (.::) :: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (h a)) -> f (g (h b)) infixr 8 .:: -- | Operator name for fmap4. (.:::) :: (Functor f, Functor g, Functor h, Functor i) => (a -> b) -> f (g (h (i a))) -> f (g (h (i b))) infixr 8 .::: -- | Operator name for fmap5. (.::::) :: (Functor f, Functor g, Functor h, Functor i, Functor j) => (a -> b) -> f (g (h (i (j a)))) -> f (g (h (i (j b)))) infixr 8 .:::: -- | Operator name for fmap6. (.:::::) :: (Functor f, Functor g, Functor h, Functor i, Functor j, Functor k) => (a -> b) -> f (g (h (i (j (k a))))) -> f (g (h (i (j (k b))))) infixr 8 .::::: -- | Apply f to both sides of p, , ie. bimap f f. This -- is the generic version of bimap1. bimap1f :: Bifunctor p => (a -> b) -> p a a -> p b b -- | Apply f to both elements of a two-tuple. Type-specialised -- bimap1f. bimap1 :: (t -> u) -> (t, t) -> (u, u) -- | System.IO related functions. module Music.Theory.Io -- | decodeUtf8 of readFile, implemented via -- Data.Text. read_file_utf8_text :: FilePath -> IO Text -- | Read (strictly) a UTF-8 encoded text file, implemented via -- Data.Text. read_file_utf8 :: FilePath -> IO String -- | read_file_utf8, or a default value if the file doesn't exist. read_file_utf8_or :: String -> FilePath -> IO String -- | Write UTF8 string as file, via Data.Text. write_file_utf8 :: FilePath -> String -> IO () -- | readFile variant using Text for ISO 8859-1 -- (Latin 1) encoding. read_file_iso_8859_1 :: FilePath -> IO String -- | readFile variant using Text for local encoding. read_file_locale :: FilePath -> IO String -- | Interact with files. Like Prelude.interact, but with named files. interactWithFiles :: FilePath -> FilePath -> (String -> String) -> IO () -- | Get line from stdin if there is any input, else Nothing. getLineFromStdinIfReady :: IO (Maybe String) -- | Wait for input to be available, and then get lines while input remains -- available. getAvailableLinesFromStdin :: IO [String] -- | Interact with stdin and stdout. Like Prelude.interact, but with pipes. interactWithStdio :: (String -> String) -> IO () -- | List functions. module Music.Theory.List -- | slice, ie. starting index (zero-indexed) and number of -- elements. -- --
-- slice 4 5 [1..] == [5,6,7,8,9] --slice :: Int -> Int -> [a] -> [a] -- | Variant of slice with start and end indices (zero-indexed). -- --
-- section 4 8 [1..] == [5,6,7,8,9] --section :: Int -> Int -> [a] -> [a] -- | Bracket sequence with left and right values. -- --
-- bracket ('<','>') "1,2,3" == "<1,2,3>"
--
bracket :: (a, a) -> [a] -> [a]
-- | Variant where brackets are sequences.
--
--
-- bracket_l ("<:",":>") "1,2,3" == "<:1,2,3:>"
--
bracket_l :: ([a], [a]) -> [a] -> [a]
-- | The first & middle & last elements of a list.
--
--
-- map unbracket_el ["","{12}"] == [(Nothing,"",Nothing),(Just '{',"12",Just '}')]
--
unbracket_el :: [a] -> (Maybe a, [a], Maybe a)
-- | The first & middle & last elements of a list.
--
--
-- map unbracket ["","{12}"] == [Nothing,Just ('{',"12",'}')]
--
unbracket :: [t] -> Maybe (t, [t], t)
-- | Erroring variant.
unbracket_err :: [t] -> (t, [t], t)
-- | Relative of splitOn, but only makes first separation.
--
--
-- splitOn "//" "lhs//rhs//rem" == ["lhs","rhs","rem"]
-- separate_at "//" "lhs//rhs//rem" == Just ("lhs","rhs//rem")
--
separate_at :: Eq a => [a] -> [a] -> Maybe ([a], [a])
-- | Variant of splitWhen that keeps delimiters at left.
--
-- -- split_when_keeping_left (== 'r') "rab rcd re rf r" == ["","rab ","rcd ","re ","rf ","r"] --split_when_keeping_left :: (a -> Bool) -> [a] -> [[a]] -- | Split before the indicated element, keeping it at the left of the -- sub-sequence it begins. split_when_keeping_left of == -- --
-- split_before 'x' "axbcxdefx" == ["a","xbc","xdef","x"] -- split_before 'x' "xa" == ["","xa"] ---- --
-- map (flip split_before "abcde") "ae_" == [["","abcde"],["abcd","e"],["abcde"]]
-- map (flip break "abcde" . (==)) "ae_" == [("","abcde"),("abcd","e"),("abcde","")]
--
--
-- -- split_before 'r' "rab rcd re rf r" == ["","rab ","rcd ","re ","rf ","r"] --split_before :: Eq a => a -> [a] -> [[a]] -- | Split before any of the indicated set of delimiters. -- --
-- split_before_any ",;" ";a,b,c;d;" == ["",";a",",b",",c",";d",";"] --split_before_any :: Eq a => [a] -> [a] -> [[a]] -- | Singleton variant of splitOn. -- --
-- split_on_1 ":" "graph:layout" == Just ("graph","layout")
--
split_on_1 :: Eq t => [t] -> [t] -> Maybe ([t], [t])
-- | Erroring variant.
split_on_1_err :: Eq t => [t] -> [t] -> ([t], [t])
-- | Split function that splits only once, ie. a variant of break.
--
--
-- split1 ' ' "three word sentence" == Just ("three","word sentence")
--
split1 :: Eq a => a -> [a] -> Maybe ([a], [a])
-- | Erroring variant.
split1_err :: (Eq a, Show a) => a -> [a] -> ([a], [a])
-- | If length is not even the second "half" is longer.
--
-- -- split_into_halves [] == ([],[]) -- split_into_halves [1] == ([],[1]) -- split_into_halves [1 .. 2] == ([1],[2]) -- split_into_halves [1 .. 8] == ([1,2,3,4],[5,6,7,8]) -- split_into_halves [1 .. 9] == ([1,2,3,4],[5,6,7,8,9]) --split_into_halves :: [t] -> ([t], [t]) -- | Generic form of rotate_left. genericRotate_left :: Integral i => i -> [a] -> [a] -- | Left rotation. -- --
-- rotate_left 1 [1..3] == [2,3,1] -- rotate_left 3 [1..5] == [4,5,1,2,3] --rotate_left :: Int -> [a] -> [a] -- | Generic form of rotate_right. genericRotate_right :: Integral n => n -> [a] -> [a] -- | Right rotation. -- --
-- rotate_right 1 [1..3] == [3,1,2] --rotate_right :: Int -> [a] -> [a] -- | Rotate left by n mod #p places. Therefore -- negative n rotate right. -- --
-- rotate 1 [1..3] == [2,3,1]
-- rotate 8 [1..5] == [4,5,1,2,3]
-- (rotate (-1) "ABCD",rotate 1 "ABCD") == ("DABC","BCDA")
--
rotate :: Integral n => n -> [a] -> [a]
-- | Rotate right by n places.
--
-- -- rotate_r 8 [1..5] == [3,4,5,1,2] --rotate_r :: Integral n => n -> [a] -> [a] -- | All rotations. -- --
-- rotations [0,1,3] == [[0,1,3],[1,3,0],[3,0,1]] --rotations :: [a] -> [[a]] -- | Rotate list so that is starts at indicated element. -- --
-- rotate_starting_from 'c' "abcde" == Just "cdeab" -- rotate_starting_from '_' "abc" == Nothing --rotate_starting_from :: Eq a => a -> [a] -> Maybe [a] -- | Erroring variant. rotate_starting_from_err :: Eq a => a -> [a] -> [a] -- | Sequence of n adjacent elements, moving forward by k -- places. The last element may have fewer than n places, but will -- reach the end of the input sequence. -- --
-- adj 3 2 "adjacent" == ["adj","jac","cen","nt"] --adj :: Int -> Int -> [a] -> [[a]] -- | Variant of adj where the last element has n places but -- may not reach the end of the input sequence. -- --
-- adj_trunc 4 1 "adjacent" == ["adja","djac","jace","acen","cent"] -- adj_trunc 3 2 "adjacent" == ["adj","jac","cen"] --adj_trunc :: Int -> Int -> [a] -> [[a]] -- | adj_trunc of close by n-1. -- --
-- adj_cyclic_trunc 3 1 "adjacent" == ["adj","dja","jac","ace","cen","ent","nta","tad"] --adj_cyclic_trunc :: Int -> Int -> [a] -> [[a]] -- | Generic form of adj2. genericAdj2 :: Integral n => n -> [t] -> [(t, t)] -- | Adjacent elements of list, at indicated distance, as pairs. -- --
-- adj2 1 [1..5] == [(1,2),(2,3),(3,4),(4,5)] -- let l = [1..5] in zip l (tail l) == adj2 1 l -- adj2 2 [1..4] == [(1,2),(3,4)] -- adj2 3 [1..5] == [(1,2),(4,5)] --adj2 :: Int -> [t] -> [(t, t)] -- | Append first n-elements to end of list. -- --
-- close 1 [1..3] == [1,2,3,1] --close :: Int -> [a] -> [a] -- | adj2 . close 1. -- --
-- adj2_cyclic 1 [1..3] == [(1,2),(2,3),(3,1)] --adj2_cyclic :: Int -> [t] -> [(t, t)] -- | Adjacent triples. -- --
-- adj3 3 [1..6] == [(1,2,3),(4,5,6)] --adj3 :: Int -> [t] -> [(t, t, t)] -- | adj3 . close 2. -- --
-- adj3_cyclic 1 [1..4] == [(1,2,3),(2,3,4),(3,4,1),(4,1,2)] --adj3_cyclic :: Int -> [t] -> [(t, t, t)] -- | Adjacent quadruples. -- --
-- adj4 2 [1..8] == [(1,2,3,4),(3,4,5,6),(5,6,7,8)] -- adj4 4 [1..8] == [(1,2,3,4),(5,6,7,8)] --adj4 :: Int -> [t] -> [(t, t, t, t)] -- | Interleave elements of p and q. If not of equal length -- elements are discarded. -- --
-- interleave [1..3] [4..6] == [1,4,2,5,3,6] -- interleave ".+-" "abc" == ".a+b-c" -- interleave [1..3] [] == [] --interleave :: [a] -> [a] -> [a] -- | Interleave list of lists. Allows lists to be of non-equal lenghts. -- --
-- interleave_set ["abcd","efgh","ijkl"] == "aeibfjcgkdhl" -- interleave_set ["abc","defg","hijkl"] == "adhbeicfjgkl" --interleave_set :: [[a]] -> [a] -- | De-interleave n lists. -- --
-- deinterleave 2 ".a+b-c" == [".+-","abc"] -- deinterleave 3 "aeibfjcgkdhl" == ["abcd","efgh","ijkl"] --deinterleave :: Int -> [a] -> [[a]] -- | Special case for two-part deinterleaving. -- --
-- deinterleave2 ".a+b-c" == (".+-","abc")
--
deinterleave2 :: [t] -> ([t], [t])
-- | Variant that continues with the longer input.
--
-- -- interleave_continue ".+-" "abc" == ".a+b-c" -- interleave_continue [1..3] [] == [1..3] -- interleave_continue [] [1..3] == [1..3] --interleave_continue :: [a] -> [a] -> [a] -- | interleave of rotate_left by i and j. -- --
-- interleave_rotations 9 3 [1..13] == [10,4,11,5,12,6,13,7,1,8,2,9,3,10,4,11,5,12,6,13,7,1,8,2,9,3] --interleave_rotations :: Int -> Int -> [b] -> [b] -- | unzip, apply f1 and f2 and zip. rezip :: ([t] -> [u]) -> ([v] -> [w]) -> [(t, v)] -> [(u, w)] -- | Generalised histogram, with equality function for grouping and -- comparison function for sorting. generic_histogram_by :: Integral i => (a -> a -> Bool) -> Maybe (a -> a -> Ordering) -> [a] -> [(a, i)] -- | Type specialised generic_histogram_by. histogram_by :: (a -> a -> Bool) -> Maybe (a -> a -> Ordering) -> [a] -> [(a, Int)] -- | Count occurences of elements in list, histogram_by of == -- and compare. generic_histogram :: (Ord a, Integral i) => [a] -> [(a, i)] -- | Type specialised generic_histogram. Elements will be in -- ascending order. -- --
-- map histogram ["","hohoh","yxx"] == [[],[('h',3),('o',2)],[('x',2),('y',1)]]
--
histogram :: Ord a => [a] -> [(a, Int)]
-- | Join two histograms, which must be sorted.
--
-- -- histogram_join (zip "ab" [1,1]) (zip "bc" [1,1]) == zip "abc" [1,2,1] --histogram_join :: Ord a => [(a, Int)] -> [(a, Int)] -> [(a, Int)] -- | foldr of histogram_join. -- --
-- let f x = zip x (repeat 1) in histogram_merge (map f ["ab","bcd","de"]) == zip "abcde" [1,2,1,2,1] --histogram_merge :: Ord a => [[(a, Int)]] -> [(a, Int)] -- | Given (k,#) histogram where k is enumerable generate filled histogram -- with 0 for empty k. -- --
-- histogram_fill (histogram "histogram") == zip ['a'..'t'] [1,0,0,0,0,0,1,1,1,0,0,0,1,0,1,0,0,1,1,1] --histogram_fill :: (Ord a, Enum a) => [(a, Int)] -> [(a, Int)] -- | Given two histograms p & q (sorted by key) make composite -- histogram giving for all keys the counts for (p,q). -- --
-- r = zip "ABCDE" (zip [4,3,2,1,0] [2,3,4,0,5]) -- histogram_composite (zip "ABCD" [4,3,2,1]) (zip "ABCE" [2,3,4,5]) == r --histogram_composite :: Ord a => [(a, Int)] -> [(a, Int)] -> [(a, (Int, Int))] -- | Apply - at count of histogram_composite, ie. 0 indicates -- equal number at p and q, negative indicates more elements at p than q -- and positive more elements at q than p. -- --
-- histogram_diff (zip "ABCD" [4,3,2,1]) (zip "ABCE" [2,3,4,5]) == zip "ABCDE" [-2,0,2,-1,5] --histogram_diff :: Ord a => [(a, Int)] -> [(a, Int)] -> [(a, Int)] -- | Elements that appear more than once in the input given equality -- predicate. duplicates_by :: Ord a => (a -> a -> Bool) -> [a] -> [a] -- | duplicates_by of ==. -- --
-- map duplicates ["duplicates","redundant"] == ["","dn"] --duplicates :: Ord a => [a] -> [a] -- | List segments of length i at distance j. -- --
-- segments 2 1 [1..5] == [[1,2],[2,3],[3,4],[4,5]] -- segments 2 2 [1..5] == [[1,2],[3,4]] --segments :: Int -> Int -> [a] -> [[a]] -- | foldl1 intersect. -- --
-- intersect_l [[1,2],[1,2,3],[1,2,3,4]] == [1,2] --intersect_l :: Eq a => [[a]] -> [a] -- | foldl1 union. -- --
-- sort (union_l [[1,3],[2,3],[3]]) == [1,2,3] --union_l :: Eq a => [[a]] -> [a] -- | Intersection of adjacent elements of list at distance n. -- --
-- adj_intersect 1 [[1,2],[1,2,3],[1,2,3,4]] == [[1,2],[1,2,3]] --adj_intersect :: Eq a => Int -> [[a]] -> [[a]] -- | List of cycles at distance n. -- --
-- cycles 2 [1..6] == [[1,3,5],[2,4,6]] -- cycles 3 [1..9] == [[1,4,7],[2,5,8],[3,6,9]] -- cycles 4 [1..8] == [[1,5],[2,6],[3,7],[4,8]] --cycles :: Int -> [a] -> [[a]] -- | Variant of filter that has a predicate to halt processing, ie. -- filter of takeWhile. -- --
-- filter_halt (even . fst) ((< 5) . snd) (zip [1..] [0..]) --filter_halt :: (a -> Bool) -> (a -> Bool) -> [a] -> [a] -- | Variant of filter that retains Nothing as a placeholder -- for removed elements. -- --
-- filter_maybe even [1..4] == [Nothing,Just 2,Nothing,Just 4] --filter_maybe :: (a -> Bool) -> [a] -> [Maybe a] -- | Select only the elements from the list that lie in the indicated -- range, which is (inclusive, exclusive). -- --
-- filterInRange (3, 5) [1, 1.5 .. 9] == [3.0,3.5,4.0,4.5] --filterInRange :: Ord a => (a, a) -> [a] -> [a] -- | Replace all p with q in s. -- --
-- replace "_x_" "-X-" "an _x_ string" == "an -X- string" -- replace "ab" "cd" "ab ab cd ab" == "cd cd cd cd" --replace :: Eq a => [a] -> [a] -> [a] -> [a] -- | Replace the ith value at ns with x. -- --
-- replace_at "test" 2 'n' == "tent" --replace_at :: Integral i => [a] -> i -> a -> [a] -- | Data.List.stripPrefix, which however hugs doesn't know of. strip_prefix :: Eq a => [a] -> [a] -> Maybe [a] -- | error of stripPrefix strip_prefix_err :: Eq t => [t] -> [t] -> [t] -- | Equivalent to groupBy eq on f. -- --
-- group_by_on (==) snd (zip [0..] "abbc") == [[(0,'a')],[(1,'b'),(2,'b')],[(3,'c')]] --group_by_on :: (x -> x -> Bool) -> (t -> x) -> [t] -> [[t]] -- | group_by_on of ==. -- --
-- r = [[(1,'a'),(1,'b')],[(2,'c')],[(3,'d'),(3,'e')],[(4,'f')]] -- group_on fst (zip [1,1,2,3,3,4] "abcdef") == r --group_on :: Eq x => (a -> x) -> [a] -> [[a]] -- | Given an equality predicate and accesors for key and -- value collate adjacent values. collate_by_on_adjacent :: (k -> k -> Bool) -> (a -> k) -> (a -> v) -> [a] -> [(k, [v])] -- | collate_by_on_adjacent of == collate_on_adjacent :: Eq k => (a -> k) -> (a -> v) -> [a] -> [(k, [v])] -- | collate_on_adjacent of fst and snd. -- --
-- collate_adjacent (zip "TDD" "xyz") == [('T',"x"),('D',"yz")]
--
collate_adjacent :: Eq a => [(a, b)] -> [(a, [b])]
-- | Data.List.sortOn, which however hugs doesn't know of.
sort_on :: Ord b => (a -> b) -> [a] -> [a]
-- | sortOn prior to collate_on_adjacent.
--
--
-- r = [('A',"a"),('B',"bd"),('C',"ce"),('D',"f")]
-- collate_on fst snd (zip "ABCBCD" "abcdef") == r
--
collate_on :: Ord k => (a -> k) -> (a -> v) -> [a] -> [(k, [v])]
-- | collate_on of fst and snd.
--
--
-- collate (zip "TDD" "xyz") == [('D',"yz"),('T',"x")]
-- collate (zip [1,2,1] "abc") == [(1,"ac"),(2,"b")]
--
collate :: Ord a => [(a, b)] -> [(a, [b])]
-- | Reverse of collate, inverse if order is not considered.
--
-- -- uncollate [(1,"ac"),(2,"b")] == zip [1,1,2] "acb" --uncollate :: [(k, [v])] -> [(k, v)] -- | Make assoc list with given key. -- --
-- with_key 'a' [1..3] == [('a',1),('a',2),('a',3)]
--
with_key :: k -> [v] -> [(k, v)]
-- | Left biased merge of association lists p and q.
--
-- -- assoc_merge [(5,"a"),(3,"b")] [(5,"A"),(7,"C")] == [(5,"a"),(3,"b"),(7,"C")] --assoc_merge :: Eq k => [(k, v)] -> [(k, v)] -> [(k, v)] -- | Keys are in ascending order, the entry retrieved is the rightmose with -- a key less than or equal to the key requested. If the key requested is -- less than the initial key, or the list is empty, returns -- Nothing. -- --
-- let m = [(1,'a'),(4,'x'),(4,'b'),(5,'c')] -- mapMaybe (ord_map_locate m) [1 .. 6] == [(1,'a'),(1,'a'),(1,'a'),(4,'b'),(5,'c'),(5,'c')] -- ord_map_locate m 0 == Nothing --ord_map_locate :: Ord k => [(k, v)] -> k -> Maybe (k, v) -- | Intervals to values, zero is n. -- --
-- dx_d 5 [1,2,3] == [5,6,8,11] --dx_d :: Num a => a -> [a] -> [a] -- | Variant that takes initial value and separates final value. This is an -- appropriate function for mapAccumL. -- --
-- dx_d' 5 [1,2,3] == (11,[5,6,8]) -- dx_d' 0 [1,1,1] == (3,[0,1,2]) --dx_d' :: Num t => t -> [t] -> (t, [t]) -- | Integration with f, ie. apply flip of f between elements -- of l. -- --
-- d_dx_by (,) "abcd" == [('b','a'),('c','b'),('d','c')]
-- d_dx_by (-) [0,2,4,1,0] == [2,2,-3,-1]
-- d_dx_by (-) [2,3,0,4,1] == [1,-3,4,-3]
--
d_dx_by :: (t -> t -> u) -> [t] -> [u]
-- | Integrate, d_dx_by -, ie. pitch class segment to
-- interval sequence.
--
-- -- d_dx [5,6,8,11] == [1,2,3] -- d_dx [] == [] --d_dx :: Num a => [a] -> [a] -- | Elements of p not in q. -- --
-- [1,2,3] `difference` [1,2] == [3] --difference :: Eq a => [a] -> [a] -> [a] -- | Is p a subset of q, ie. is intersect of p -- and q == p. -- --
-- map (is_subset [1,2]) [[1],[1,2],[1,2,3]] == [False,True,True] --is_subset :: Eq a => [a] -> [a] -> Bool -- | Is p a proper subset of q, is_subset and -- not equal. -- --
-- map (is_proper_subset [1,2]) [[1],[1,2],[1,2,3]] == [False,False,True] --is_proper_subset :: Eq a => [a] -> [a] -> Bool -- | Is p a superset of q, ie. flip is_subset. -- --
-- is_superset [1,2,3] [1,2] == True --is_superset :: Eq a => [a] -> [a] -> Bool -- | Is p a subsequence of q, ie. synonym for -- isInfixOf. -- --
-- subsequence [1,2] [1,2,3] == True --subsequence :: Eq a => [a] -> [a] -> Bool -- | Erroring variant of findIndex. findIndex_err :: (a -> Bool) -> [a] -> Int -- | Erroring variant of elemIndex. elemIndex_err :: Eq a => a -> [a] -> Int -- | Variant of elemIndices that requires e to be unique in -- p. -- --
-- elem_index_unique 'a' "abcda" == undefined --elem_index_unique :: Eq a => a -> [a] -> Int -- | Lookup that errors and prints message and key. lookup_err_msg :: (Eq k, Show k) => String -> k -> [(k, v)] -> v -- | Error variant. lookup_err :: Eq k => k -> [(k, v)] -> v -- | lookup variant with default value. lookup_def :: Eq k => k -> v -> [(k, v)] -> v -- | If l is empty Nothing, else Just l. non_empty :: [t] -> Maybe [t] -- | Variant on filter that selects all matches. -- --
-- lookup_set 1 (zip [1,2,3,4,1] "abcde") == Just "ae" --lookup_set :: Eq k => k -> [(k, v)] -> Maybe [v] -- | Erroring variant. lookup_set_err :: Eq k => k -> [(k, v)] -> [v] -- | Reverse lookup. -- --
-- reverse_lookup 'c' [] == Nothing -- reverse_lookup 'b' (zip [1..] ['a'..]) == Just 2 -- lookup 2 (zip [1..] ['a'..]) == Just 'b' --reverse_lookup :: Eq v => v -> [(k, v)] -> Maybe k -- | Erroring variant. reverse_lookup_err :: Eq v => v -> [(k, v)] -> k -- | Erroring variant of find. find_err :: (t -> Bool) -> [t] -> t -- | Basis of find_bounds_scl, indicates if x is to the left -- or right of the list, and if to the right whether equal or not. -- Right values will be correct if the list is not ascending, -- however Left values only make sense for ascending ranges. -- --
-- map (find_bounds_cmp compare [(0,1),(1,2)]) [-1,0,1,2,3] --find_bounds_cmp :: (t -> s -> Ordering) -> [(t, t)] -> s -> Either ((t, t), Ordering) (t, t) -- | Decide if value is nearer the left or right value of a range, return -- fst or snd. decide_nearest_f :: Ord o => Bool -> (p -> o) -> (p, p) -> (x, x) -> x -- | decide_nearest_f with abs of - as measure. -- --
-- (decide_nearest True 2 (1,3)) ("left","right") == "left"
--
decide_nearest :: (Num o, Ord o) => Bool -> o -> (o, o) -> (x, x) -> x
-- | sel_f gets comparison key from t.
find_nearest_by :: (Ord n, Num n) => (t -> n) -> Bool -> [t] -> n -> t
-- | Find the number that is nearest the requested value in an ascending
-- list of numbers.
--
-- -- map (find_nearest_err True [0,3.5,4,7]) [-1,1,3,5,7,9] == [0,0,3.5,4,7,7] --find_nearest_err :: (Num n, Ord n) => Bool -> [n] -> n -> n -- | find_nearest_err allowing null input list (which returns -- Nothing) find_nearest :: (Num n, Ord n) => Bool -> [n] -> n -> Maybe n -- | Basis of find_bounds. There is an option to consider the last -- element specially, and if equal to the last span is given. -- -- scl=special-case-last find_bounds_scl :: Bool -> (t -> s -> Ordering) -> [(t, t)] -> s -> Maybe (t, t) -- | Find adjacent elements of list that bound element under given -- comparator. -- --
-- let {f = find_bounds True compare [1..5]
-- ;r = [Nothing,Just (1,2),Just (3,4),Just (4,5)]}
-- in map f [0,1,3.5,5] == r
--
find_bounds :: Bool -> (t -> s -> Ordering) -> [t] -> s -> Maybe (t, t)
-- | Special case of dropRight.
--
-- -- map drop_last ["","?","remove"] == ["","","remov"] --drop_last :: [t] -> [t] -- | Variant of drop from right of list. -- --
-- dropRight 1 [1..9] == [1..8] --dropRight :: Int -> [a] -> [a] -- | Variant of dropWhile from right of list. -- --
-- dropWhileRight Data.Char.isDigit "A440" == "A" --dropWhileRight :: (a -> Bool) -> [a] -> [a] -- | Data.List.dropWhileEnd, which however hugs doesn't know of. drop_while_end :: (a -> Bool) -> [a] -> [a] -- | foldr form of dropWhileRight. -- --
-- drop_while_right Data.Char.isDigit "A440" == "A" --drop_while_right :: (a -> Bool) -> [a] -> [a] -- | take from right. -- --
-- take_right 3 "taking" == "ing" --take_right :: Int -> [a] -> [a] -- | takeWhile from right. -- --
-- takeWhileRight Data.Char.isDigit "A440" == "440" --takeWhileRight :: (a -> Bool) -> [a] -> [a] -- | foldr form of takeWhileRight. -- --
-- take_while_right Data.Char.isDigit "A440" == "440" --take_while_right :: (a -> Bool) -> [a] -> [a] -- | Variant of take that allows Nothing to indicate the -- complete list. -- --
-- maybe_take (Just 5) [1 .. ] == [1 .. 5] -- maybe_take Nothing [1 .. 9] == [1 .. 9] --maybe_take :: Maybe Int -> [a] -> [a] -- | Take until f is true. This is not the same as not at -- takeWhile because it keeps the last element. It is an error if -- the predicate never succeeds. -- --
-- take_until (== 'd') "tender" == "tend" -- takeWhile (not . (== 'd')) "tend" == "ten" -- take_until (== 'd') "seven" == undefined --take_until :: (a -> Bool) -> [a] -> [a] -- | Apply f at first element, and g at all other elements. -- --
-- at_head negate id [1..5] == [-1,2,3,4,5] --at_head :: (a -> b) -> (a -> b) -> [a] -> [b] -- | Apply f at all but last element, and g at last element. -- --
-- at_last (* 2) negate [1..4] == [2,4,6,-4] --at_last :: (a -> b) -> (a -> b) -> [a] -> [b] -- | Separate list into an initial list and perhaps the last element tuple. -- --
-- separate_last' [] == ([],Nothing) --separate_last' :: [a] -> ([a], Maybe a) -- | Error on null input. -- --
-- separate_last [1..5] == ([1..4],5) --separate_last :: [a] -> ([a], a) -- | Replace directly repeated elements with Nothing. -- --
-- indicate_repetitions "abba" == [Just 'a',Just 'b',Nothing,Just 'a'] --indicate_repetitions :: Eq a => [a] -> [Maybe a] -- | zipWith of list and it's own tail. -- --
-- zip_with_adj (,) "abcde" == [('a','b'),('b','c'),('c','d'),('d','e')]
--
zip_with_adj :: (a -> a -> b) -> [a] -> [b]
-- | Type-specialised zip_with_adj.
compare_adjacent_by :: (a -> a -> Ordering) -> [a] -> [Ordering]
-- | compare_adjacent_by of compare.
--
-- -- compare_adjacent [0,1,3,2] == [LT,LT,GT] --compare_adjacent :: Ord a => [a] -> [Ordering] -- | Head and tail of list. Useful to avoid "incomplete-uni-patterns" -- warnings. It's an error if the list is empty. headTail :: [a] -> (a, [a]) -- | First and second elements of list. Useful to avoid -- "incomplete-uni-patterns" warnings. It's an error if the list has less -- than two elements. firstSecond :: [t] -> (t, t) -- | groupBy does not make adjacent comparisons, it compares each -- new element to the start of the group. This function is the adjacent -- variant. -- --
-- groupBy (<) [1,2,3,2,4,1,5,9] == [[1,2,3,2,4],[1,5,9]] -- adjacent_groupBy (<) [1,2,3,2,4,1,5,9] == [[1,2,3],[2,4],[1,5,9]] --adjacent_groupBy :: (a -> a -> Bool) -> [a] -> [[a]] -- | Reduce sequences of consecutive values to ranges. -- --
-- group_ranges [-1,0,3,4,5,8,9,12] == [(-1,0),(3,5),(8,9),(12,12)] -- group_ranges [3,2,3,4,3] == [(3,3),(2,4),(3,3)] --group_ranges :: (Num t, Eq t) => [t] -> [(t, t)] -- | groupBy on structure of Maybe, ie. all -- Just compare equal. -- --
-- let r = [[Just 1],[Nothing,Nothing],[Just 4,Just 5]] -- in group_just [Just 1,Nothing,Nothing,Just 4,Just 5] == r --group_just :: [Maybe a] -> [[Maybe a]] -- | Predicate to determine if all elements of the list are ==. -- --
-- all_equal "aaa" == True --all_equal :: Eq a => [a] -> Bool -- | Variant using nub. all_eq :: Eq n => [n] -> Bool -- | nubBy == on f. -- --
-- nub_on snd (zip "ABCD" "xxyy") == [('A','x'),('C','y')]
--
nub_on :: Eq b => (a -> b) -> [a] -> [a]
-- | group_on of sortOn.
--
--
-- let r = [[('1','a'),('1','c')],[('2','d')],[('3','b'),('3','e')]]
-- in sort_group_on fst (zip "13123" "abcde") == r
--
sort_group_on :: Ord b => (a -> b) -> [a] -> [[a]]
-- | Maybe cons element onto list.
--
-- -- Nothing `mcons` "something" == "something" -- Just 's' `mcons` "omething" == "something" --mcons :: Maybe a -> [a] -> [a] -- | Cons onto end of list. -- --
-- snoc 4 [1,2,3] == [1,2,3,4] --snoc :: a -> [a] -> [a] -- | Comparison function type. type Compare_F a = a -> a -> Ordering -- | If f compares EQ, defer to g. two_stage_compare :: Compare_F a -> Compare_F a -> Compare_F a -- | compare on of two_stage_compare two_stage_compare_on :: (Ord i, Ord j) => (t -> i) -> (t -> j) -> t -> t -> Ordering -- | Sequence of comparison functions, continue comparing until not EQ. -- --
-- compare (1,0) (0,1) == GT -- n_stage_compare [compare `on` snd,compare `on` fst] (1,0) (0,1) == LT --n_stage_compare :: [Compare_F a] -> Compare_F a -- | compare on of two_stage_compare n_stage_compare_on :: Ord i => [t -> i] -> t -> t -> Ordering -- | Sort sequence a based on ordering of sequence b. -- --
-- sort_to "abc" [1,3,2] == "acb" -- sort_to "adbce" [1,4,2,3,5] == "abcde" --sort_to :: Ord i => [e] -> [i] -> [e] -- | flip of sort_to. -- --
-- sort_to_rev [1,4,2,3,5] "adbce" == "abcde" --sort_to_rev :: Ord i => [i] -> [e] -> [e] -- | sortBy of two_stage_compare. sort_by_two_stage :: Compare_F a -> Compare_F a -> [a] -> [a] -- | sortBy of n_stage_compare. sort_by_n_stage :: [Compare_F a] -> [a] -> [a] -- | sortBy of two_stage_compare_on. sort_by_two_stage_on :: (Ord b, Ord c) => (a -> b) -> (a -> c) -> [a] -> [a] -- | sortBy of n_stage_compare_on. sort_by_n_stage_on :: Ord b => [a -> b] -> [a] -> [a] -- | Given a comparison function, merge two ascending lists. Alias for -- mergeBy -- --
-- merge_by compare [1,3,5] [2,4] == [1..5] --merge_by :: Compare_F a -> [a] -> [a] -> [a] -- | merge_by compare on. merge_on :: Ord x => (a -> x) -> [a] -> [a] -> [a] -- | mergeBy of two_stage_compare. merge_by_two_stage :: Ord b => (a -> b) -> Compare_F c -> (a -> c) -> [a] -> [a] -> [a] -- | Alias for merge merge :: Ord a => [a] -> [a] -> [a] -- | Merge list of sorted lists given comparison function. Note that this -- is not equal to mergeAll. merge_set_by :: (a -> a -> Ordering) -> [[a]] -> [a] -- | merge_set_by of compare. -- --
-- merge_set [[1,3,5,7,9],[2,4,6,8],[10]] == [1..10] --merge_set :: Ord a => [[a]] -> [a] -- | merge_by variant that joins (resolves) equal elements. -- --
-- let {left p _ = p
-- ;right _ q = q
-- ;cmp = compare `on` fst
-- ;p = zip [1,3,5] "abc"
-- ;q = zip [1,2,3] "ABC"
-- ;left_r = [(1,'a'),(2,'B'),(3,'b'),(5,'c')]
-- ;right_r = [(1,'A'),(2,'B'),(3,'C'),(5,'c')]}
-- in merge_by_resolve left cmp p q == left_r &&
-- merge_by_resolve right cmp p q == right_r
--
--
-- -- merge_by_resolve (\x _ -> x) (compare `on` fst) [(0,'A'),(1,'B'),(4,'E')] (zip [1..] "bcd") --merge_by_resolve :: (a -> a -> a) -> Compare_F a -> [a] -> [a] -> [a] -- | Merge two sorted (ascending) sequences. Where elements compare equal, -- select element from left input. -- --
-- asc_seq_left_biased_merge_by (compare `on` fst) [(0,'A'),(1,'B'),(4,'E')] (zip [1..] "bcd") --asc_seq_left_biased_merge_by :: (a -> a -> Ordering) -> [a] -> [a] -> [a] -- | Find the first two adjacent elements for which f is True. -- --
-- find_adj (>) [1,2,3,3,2,1] == Just (3,2) -- find_adj (>=) [1,2,3,3,2,1] == Just (3,3) --find_adj :: (a -> a -> Bool) -> [a] -> Maybe (a, a) -- | find_adj of >= -- --
-- filter is_ascending (words "A AA AB ABB ABC ABA") == words "A AB ABC" --is_ascending :: Ord a => [a] -> Bool -- | find_adj of > -- --
-- filter is_non_descending (words "A AA AB ABB ABC ABA") == ["A","AA","AB","ABB","ABC"] --is_non_descending :: Ord a => [a] -> Bool -- | Variant of elem that operates on a sorted list, halting. This -- is member. -- --
-- 16 `elem_ordered` [1,3 ..] == False -- 16 `elem` [1,3 ..] == undefined --elem_ordered :: Ord t => t -> [t] -> Bool -- | Variant of elemIndex that operates on a sorted list, halting. -- --
-- 16 `elemIndex_ordered` [1,3 ..] == Nothing -- 16 `elemIndex_ordered` [0,1,4,9,16,25,36,49,64,81,100] == Just 4 --elemIndex_ordered :: Ord t => t -> [t] -> Maybe Int -- | zipWith variant equivalent to mapMaybe (ie. -- catMaybes of zipWith) zip_with_maybe :: (a -> b -> Maybe c) -> [a] -> [b] -> [c] -- | zipWith variant that extends shorter side using given value. zip_with_ext :: t -> u -> (t -> u -> v) -> [t] -> [u] -> [v] -- | zip_with_ext of ',' -- --
-- let f = zip_ext 'i' 'j' -- f "" "" == [] -- f "p" "" == zip "p" "j" -- f "" "q" == zip "i" "q" -- f "pp" "q" == zip "pp" "qj" -- f "p" "qq" == zip "pi" "qq" --zip_ext :: t -> u -> [t] -> [u] -> [(t, u)] -- | Keep right variant of zipWith, where unused rhs values are -- returned. -- --
-- zip_with_kr (,) [1..3] ['a'..'e'] == ([(1,'a'),(2,'b'),(3,'c')],"de") --zip_with_kr :: (a -> b -> c) -> [a] -> [b] -> ([c], [b]) -- | A zipWith variant that always consumes an element from the left -- hand side (lhs), but only consumes an element from the right hand side -- (rhs) if the zip function is Right and not if Left. -- There's also a secondary function to continue if the rhs ends before -- the lhs. zip_with_perhaps_rhs :: (a -> b -> Either c c) -> (a -> c) -> [a] -> [b] -> [c] -- | Zip a list with a list of lists. Ordinarily the list has at least as -- many elements as there are elements at the list of lists. There is -- also a Traversable form of this called -- adopt_shape_2_zip_stream. -- --
-- zip_list_with_list_of_list [1 ..] ["a", "list", "of", "strings"] -- zip_list_with_list_of_list [1 .. 9] ["a", "list", "of", "strings"] --zip_list_with_list_of_list :: [p] -> [[q]] -> [[(p, q)]] -- | Fill gaps in a sorted association list, range is inclusive at both -- ends. -- --
-- let r = [(1,'a'),(2,'x'),(3,'x'),(4,'x'),(5,'b'),(6,'x'),(7,'c'),(8,'x'),(9,'x')] -- in fill_gaps_ascending' 'x' (1,9) (zip [1,5,7] "abc") == r --fill_gaps_ascending :: (Enum n, Ord n) => t -> (n, n) -> [(n, t)] -> [(n, t)] -- | Direct definition. fill_gaps_ascending' :: (Num n, Enum n, Ord n) => t -> (n, n) -> [(n, t)] -> [(n, t)] -- | Variant with default value for empty input list case. minimumBy_or :: t -> (t -> t -> Ordering) -> [t] -> t -- | minimum and maximum in one pass. -- --
-- minmax "minmax" == ('a','x')
--
minmax :: Ord t => [t] -> (t, t)
-- | Append k to the right of l until result has n
-- places. Truncates long input lists.
--
-- -- map (pad_right '0' 2 . return) ['0' .. '9'] -- pad_right '0' 12 "1101" == "110100000000" -- map (pad_right ' '3) ["S","E-L"] == ["S ","E-L"] -- pad_right '!' 3 "truncate" == "tru" --pad_right :: a -> Int -> [a] -> [a] -- | Variant that errors if the input list has more than n places. -- --
-- map (pad_right_err '!' 3) ["x","xy","xyz","xyz!"] --pad_right_err :: t -> Int -> [t] -> [t] -- | Variant that will not truncate long inputs. -- --
-- pad_right_no_truncate '!' 3 "truncate" == "truncate" --pad_right_no_truncate :: a -> Int -> [a] -> [a] -- | Append k to the left of l until result has n -- places. -- --
-- map (pad_left '0' 2 . return) ['0' .. '9'] --pad_left :: a -> Int -> [a] -> [a] -- | Locate first (leftmost) embedding of q in p. Return -- partial indices for failure at Left. -- --
-- embedding ("embedding","ming") == Right [1,6,7,8]
-- embedding ("embedding","mind") == Left [1,6,7]
--
embedding :: Eq t => ([t], [t]) -> Either [Int] [Int]
-- | fromRight of embedding
embedding_err :: Eq t => ([t], [t]) -> [Int]
-- | Does q occur in sequence, though not necessarily adjacently, in
-- p.
--
-- -- is_embedding [1 .. 9] [1,3,7] == True -- is_embedding "embedding" "ming" == True -- is_embedding "embedding" "mind" == False --is_embedding :: Eq t => [t] -> [t] -> Bool -- | Unpack one element list. unlist1 :: [t] -> Maybe t -- | Erroring variant. unlist1_err :: [t] -> t -- | Given an Ordering predicate where LT opens a group, -- GT closes a group, and EQ continues current group, -- construct tree from list. -- --
-- let l = "a {b {c d} e f} g h i"
-- let t = group_tree ((==) '{',(==) '}') l
-- catMaybes (flatten t) == l
--
--
--
-- let {d = putStrLn . drawTree . fmap show}
-- in d (group_tree ((==) '(',(==) ')') "a(b(cd)ef)ghi")
--
group_tree :: (a -> Bool, a -> Bool) -> [a] -> Tree (Maybe a)
-- | Remove element at index.
--
-- -- map (remove_ix 5) ["remove","removed"] == ["remov","removd"] -- remove_ix 5 "short" -- error --remove_ix :: Int -> [a] -> [a] -- | Delete element at ix from list (c.f. remove_ix, this has a more -- specific error if index does not exist). -- --
-- delete_at 3 "deleted" == "delted" -- delete_at 8 "deleted" -- error --delete_at :: (Eq t, Num t) => t -> [a] -> [a] -- | Select or remove elements at set of indices. operate_ixs :: Bool -> [Int] -> [a] -> [a] -- | Select elements at set of indices. -- --
-- select_ixs [1,3] "select" == "ee" --select_ixs :: [Int] -> [a] -> [a] -- | Remove elements at set of indices. -- --
-- remove_ixs [1,3,5] "remove" == "rmv" --remove_ixs :: [Int] -> [a] -> [a] -- | Replace element at i in p by application of f. -- --
-- replace_ix negate 1 [1..3] == [1,-2,3] --replace_ix :: (a -> a) -> Int -> [a] -> [a] -- | List equality, ignoring indicated indices. -- --
-- list_eq_ignoring_indices [3,5] "abcdefg" "abc.e.g" == True --list_eq_ignoring_indices :: (Eq t, Integral i) => [i] -> [t] -> [t] -> Bool -- | Edit list to have v at indices k. Replacement assoc-list -- must be ascending. All replacements must be in range. -- --
-- list_set_indices [(2,'C'),(4,'E')] "abcdefg" == "abCdEfg" -- list_set_indices [] "abcdefg" == "abcdefg" -- list_set_indices [(9,'I')] "abcdefg" == undefined --list_set_indices :: (Eq ix, Num ix) => [(ix, t)] -> [t] -> [t] -- | Variant of list_set_indices with one replacement. list_set_ix :: (Eq t, Num t) => t -> a -> [a] -> [a] -- | Cyclic indexing function. -- --
-- map (at_cyclic "cycle") [0..9] == "cyclecycle" --at_cyclic :: [a] -> Int -> a -- | Index list from the end, assuming the list is longer than n + 1. -- -- atFromEnd [1 .. 30] 0 == 30 atFromEnd [1..100] 15 == 85 atFromEnd :: [t] -> Int -> t -- | Graph types. module Music.Theory.Graph.Type v_is_normal :: [Int] -> Maybe Int v_is_normal_err :: [Int] -> Int -- | Un-directed edge equality. -- --
-- e_eq_undir (0,1) (1,0) == True --e_eq_undir :: Eq t => (t, t) -> (t, t) -> Bool -- | Sort edge. -- --
-- map e_sort [(0,1),(1,0)] == [(0,1),(0,1)] --e_sort :: Ord t => (t, t) -> (t, t) -- | (vertices,edges) type Gr t = ([t], [(t, t)]) -- | Gr is a functor. gr_map :: (t -> u) -> Gr t -> Gr u -- | (|V|,|E|) gr_degree :: Gr t -> (Int, Int) -- | Re-label graph given table. gr_relabel :: Eq t => [(t, u)] -> Gr t -> Gr u -- | If (i,j) and (j,i) are both in E delete (j,i) where i < j. gr_mk_undir :: Ord t => Gr t -> Gr t -- | List of E to G, derives V from E. eset_to_gr :: Ord t => [(t, t)] -> Gr t -- | Sort v and e. gr_sort :: Ord t => Gr t -> Gr t -- | Complete k-graph (un-directed) given list of vertices -- --
-- gr_complete_graph "xyz" == ("xyz",[('x','y'),('x','z'),('y','z')])
--
gr_complete_graph :: Ord t => [t] -> Gr t
-- | Gr of Int
type G = Gr Int
-- | Simple text representation of G. Requires (and checks) that
-- vertices are (0 .. |v|-1). The first line is the number of vertices,
-- following lines are edges.
g_to_text :: G -> String
-- | Graph to G.
graph_to_g :: Graph -> G
-- | G to Graph
--
-- -- g = ([0,1,2],[(0,1),(0,2),(1,2)]) -- g == gr_sort (graph_to_g (g_to_graph g)) --g_to_graph :: G -> Graph -- | Unlabel graph, make table. -- --
-- gr_unlabel ("xyz",[('x','y'),('x','z')]) == (([0,1,2],[(0,1),(0,2)]),[(0,'x'),(1,'y'),(2,'z')])
--
gr_unlabel :: Eq t => Gr t -> (G, [(Int, t)])
-- | fst of gr_unlabel
gr_to_g :: Eq t => Gr t -> G
-- | g_to_graph of gr_unlabel.
--
--
-- gr = ("abc",[('a','b'),('a','c'),('b','c')])
-- (g,tbl) = gr_to_graph gr
--
gr_to_graph :: Eq t => Gr t -> (Graph, [(Int, t)])
-- | Complete k-graph (un-directed).
--
-- -- g_complete_graph 3 == ([0,1,2],[(0,1),(0,2),(1,2)]) --g_complete_graph :: Int -> G -- | ((|V|,|E|),[E]) type Edg = ((Int, Int), [(Int, Int)]) -- | Requires (and checks) that vertices are (0 .. |v| - 1). g_to_edg :: G -> Edg -- | Requires (but does not check) that vertices of Edg are all in -- (0,|v| - 1). edg_to_g :: Edg -> G -- | Parse Edg as printed by nauty-listg. edg_parse :: [String] -> Edg -- | Adjacency list [(left-hand-side,[right-hand-side])] type Adj t = [(t, [t])] -- | Adj to edge set. adj_to_eset :: Ord t => Adj t -> [(t, t)] -- | Adj to Gr adj_to_gr :: Ord t => Adj t -> Gr t -- | Gr to Adj (selection-function) gr_to_adj :: Ord t => (t -> (t, t) -> Maybe t) -> Gr t -> Adj t -- | Gr to Adj (directed) -- --
-- g = ([0,1,2,3],[(0,1),(2,1),(0,3),(3,0)]) -- r = [(0,[1,3]),(2,[1]),(3,[0])] -- gr_to_adj_dir g == r --gr_to_adj_dir :: Ord t => Gr t -> Adj t -- | Gr to Adj (un-directed) -- --
-- g = ([0,1,2,3],[(0,1),(2,1),(0,3),(3,0)]) -- gr_to_adj_undir g == [(0,[1,3,3]),(1,[2])] --gr_to_adj_undir :: Ord t => Gr t -> Adj t -- | Adjacency matrix, (|v|,mtx) type Adj_Mtx t = (Int, [[t]]) -- | Edg to Adj_Mtx for un-directed graph. -- --
-- e = ((4,3),[(0,3),(1,3),(2,3)]) -- edg_to_adj_mtx_undir (0,1) e == (4,[[0,0,0,1],[0,0,0,1],[0,0,0,1],[1,1,1,0]]) ---- --
-- e = ((4,4),[(0,1),(0,3),(1,2),(2,3)]) -- edg_to_adj_mtx_undir (0,1) e == (4,[[0,1,0,1],[1,0,1,0],[0,1,0,1],[1,0,1,0]]) --edg_to_adj_mtx_undir :: (t, t) -> Edg -> Adj_Mtx t -- | edg_to_adj_mtx_undir of g_to_edg g_to_adj_mtx_undir :: (t, t) -> G -> Adj_Mtx t -- | Lookup Adj_Mtx to find connected vertices. adj_mtx_con :: Eq t => (t, t) -> Adj_Mtx t -> Int -> [Int] -- | Labelled graph, distinct vertex and edge labels. type Lbl_Gr v v_lbl e_lbl = ([(v, v_lbl)], [((v, v), e_lbl)]) -- | Lbl_Gr of Int type Lbl v e = Lbl_Gr Int v e -- | Lbl with () edge labels. type Lbl_ v = Lbl v () -- | Number of vertices and edges. lbl_degree :: Lbl v e -> (Int, Int) -- | Apply v at vertex labels and e at edge labels. lbl_bimap :: (v -> v') -> (e -> e') -> Lbl v e -> Lbl v' e' -- | Merge two Lbl graphs, do not share vertices, vertex indices at -- g1 are stable. lbl_merge :: Lbl v e -> Lbl v e -> Lbl v e -- | foldl1 of lbl_merge lbl_merge_seq :: [Lbl v e] -> Lbl v e -- | Re-write graph so vertex indices are (0 .. n-1) and vertex labels are -- unique. lbl_canonical :: (Eq v, Ord v) => Lbl v e -> Lbl v e -- | Re-write edges so that vertex indices are ascending. lbl_undir :: Lbl v e -> Lbl v e -- | Lbl path graph. lbl_path_graph :: [x] -> Lbl_ x -- | Lbl complete graph (undirected, no self-edges) lbl_complete_graph :: [x] -> Lbl_ x -- | Lookup vertex label with default value. v_label :: v -> Lbl v e -> Int -> v -- | v_label with error as default. v_label_err :: Lbl v e -> Int -> v -- | Lookup edge label with default value. e_label :: e -> Lbl v e -> (Int, Int) -> e -- | e_label with error as default. e_label_err :: Lbl v e -> (Int, Int) -> e -- | Convert from Lbl_Gr to Lbl lbl_gr_to_lbl :: Eq v => Lbl_Gr v v_lbl e_lbl -> Lbl v_lbl e_lbl -- | Convert from Gr to Lbl. -- --
-- gr_to_lbl ("ab",[('a','b')]) == ([(0,'a'),(1,'b')],[((0,1),('a','b'))])
--
gr_to_lbl :: Eq t => Gr t -> Lbl t (t, t)
-- | Delete edge labels from Lbl, replacing with ()
lbl_delete_edge_labels :: Lbl v e -> Lbl_ v
-- | lbl_delete_edge_labels of gr_to_lbl
gr_to_lbl_ :: Eq t => Gr t -> Lbl_ t
-- | Construct Lbl from set of E, derives V from E.
eset_to_lbl :: Ord t => [(t, t)] -> Lbl_ t
-- | Unlabel Lbl graph.
lbl_to_g :: Lbl v e -> G
-- | Lcf (LederbergCoxeterFrucht) notation
--
-- The notation only applies to Hamiltonian graphs, since it achieves its
-- symmetry and conciseness by placing a Hamiltonian cycle in a circular
-- embedding and then connecting specified pairs of nodes with edges.
-- (EW)
module Music.Theory.Graph.Lcf
-- | Lcf notation (l,k). ([3,-3],4) is the cubical graph.
type Lcf = ([Int], Int)
-- | Real, alias for Double
type R = Double
-- | Sequence, ie. l k times.
lcf_seq :: Lcf -> [Int]
-- | Length of lcf_seq, ie. |l|k
lcf_degree :: Lcf -> Int
-- | Lcf to Edg (an edge list)
lcf_to_edg :: Lcf -> Edg
-- | Lcf edge-list to graph labeled with circular co-ordinates.
edg_circ_gr :: R -> Edg -> Lbl (R, R) ()
-- | Lcf graph set given at
-- http://mathworld.wolfram.com/LcfNotation.html
--
-- -- length lcf_mw_set == 57 -- length (nub (map snd lcf_mw_set)) == 57 -- IE. UNIQ --lcf_mw_set :: [(String, Lcf)] -- | http://www.tcs.hut.fi/Software/bliss/fileformat.shtml module Music.Theory.Graph.Bliss -- | Problem is (n-vertices,n-edges) bliss_parse_problem :: String -> (Int, Int) -- | Vertex colour is (vertex,colour) bliss_parse_vertex_colour :: String -> (Int, Int) -- | Edge is (vertex,vertex) bliss_parse_edge :: String -> (Int, Int) -- | (problem,vertex-colours,edges) Bliss data is one-indexed. type Bliss = ((Int, Int), [(Int, Int)], [(Int, Int)]) -- | Parse Bliss bliss_parse :: String -> Bliss -- | bliss_parse of readFile bliss_load :: FilePath -> IO Bliss -- | Bliss (one-indexed) to G (zero-indexed) bliss_to_g :: Bliss -> G -- | graph6 graph encoding -- -- http://users.cecs.anu.edu.au/~bdm/nauty/ -- https://users.cecs.anu.edu.au/~bdm/data/formats.html module Music.Theory.Graph.G6 -- | Load Graph6 file, discard optional header if present. g6_load :: FilePath -> IO [String] -- | Load G6 file variant where each line is "DescriptiontG6" g6_dsc_load :: FilePath -> IO [(String, String)] -- | Call nauty-listg to transform a sequence of G6. (debian = nauty) g6_to_edg :: [String] -> IO [Edg] -- | edg_to_g of g6_to_edg g6_to_g :: [String] -> IO [G] -- | g6_to_edg of g6_dsc_load. g6_dsc_load_edg :: FilePath -> IO [(String, Edg)] -- | edg_to_g of g6_dsc_load_edg g6_dsc_load_gr :: FilePath -> IO [(String, G)] -- | Generate the text format read by nauty-amtog. -- --
-- e = ((4,3),[(0,3),(1,3),(2,3)]) -- m = T.edg_to_adj_mtx_undir (0,1) e -- putStrLn (adj_mtx_to_am m) --adj_mtx_to_am :: Adj_Mtx Int -> String -- | Call nauty-amtog to transform a sequence of Adj_Mtx to G6. -- --
-- adj_mtx_to_g6 [m,m] --adj_mtx_to_g6 :: [Adj_Mtx Int] -> IO [String] -- | adj_mtx_to_g6 of g_to_adj_mtx_undir g_to_g6 :: [G] -> IO [String] -- | writeFile of g_to_g6 g_store_g6 :: FilePath -> [G] -> IO () -- | Call nauty-labelg to canonise a set of graphs. g6_labelg :: [String] -> IO [String] -- | g6_to_g of g6_labelg of g_to_g6 -- --
-- g1 = ([0,1,2,3],[(0,3),(3,1),(3,2),(1,2)]) -- g2 = ([0,1,2,3],[(1,0),(0,3),(0,2),(2,3)]) -- [g3,g4] <- g_labelg [g1,g2] -- (g1 == g2,g3 == g4) --g_labelg :: [G] -> IO [G] -- | https://users.cecs.anu.edu.au/~bdm/plantri/plantri-guide.txt module Music.Theory.Graph.Planar -- | The 15-character header text indicating a Planar-Code file. plc_header_txt :: String -- | Read Plc header plc_header :: ByteString -> String -- | Read Plc data as list of Int plc_data :: ByteString -> [Int] -- | Calculate length of Plc data given (n-vertices,n-edges). plc_length :: (Int, Int) -> Int -- | Scan Plc data and segment after k zeros. plc_scanner :: Int -> [Int] -> ([Int], [Int]) -- | (n-vertices,clockwise-edge-sequences) type Plc = (Int, [[Int]]) plc_n_vertices :: Plc -> Int -- | Group Plc data into Plc structure. plc_group :: Int -> [Int] -> Plc -- | Segment input data into sequence of Plc. plc_segment :: [Int] -> [Plc] plc_parse :: ByteString -> [Plc] -- | Load sequence of Plc from binary Planar-Code file. plc_load :: FilePath -> IO [Plc] -- | All edges (one-indexed) at Plc plc_edge_set :: Plc -> [(Int, Int)] -- | Element in x after i, the element after the last is the -- first. -- --
-- map (plc_next_elem "abcd") "abcd" == "bcda" --plc_next_elem :: Eq t => [t] -> t -> t -- | The next edge in Plc following e. plc_next_edge :: Plc -> (Int, Int) -> (Int, Int) -- | The face of Plc starting at e (one-indexed edges). plc_face_from :: Plc -> (Int, Int) -> [(Int, Int)] -- | The set of all faces at Plc (one-indexed edges). plc_face_set :: Plc -> [[(Int, Int)]] -- | Translate Plc into un-directed G. Plc is one-indexed, G -- is zero-indexed. plc_to_g :: Plc -> G plc_stat :: FilePath -> IO (Int, [(Int, Int, Int)]) plc_stat_txt :: FilePath -> (Int, [(Int, Int, Int)]) -> [String] -- | Run "nauty-planarg" to convert (if possible) a set of G6 graphs to -- Planar-Code. g6_planarg :: [String] -> IO ByteString -- | plc_parse of g6_planarg of g_to_g6 g_to_plc :: [G] -> IO [Plc] -- | Run "nauty-planarg" to translate named G6 file to named PL file. g6_to_pl_wr :: FilePath -> FilePath -> IO () -- | Array & table functions module Music.Theory.Array -- | minmax of k. larray_bounds :: Ord k => [(k, v)] -> (k, k) -- | array of association list. larray :: Ix k => [(k, v)] -> Array k v -- | Plain list representation of a two-dimensional table of a in -- row-order. Tables are regular, ie. all rows have equal numbers of -- columns. type Table a = [[a]] -- | Table row count. tbl_rows :: Table t -> Int -- | Table column count, assumes table is regular. tbl_columns :: Table t -> Int -- | Determine is table is regular, ie. all rows have the same number of -- columns. -- --
-- tbl_is_regular [[0..3],[4..7],[8..11]] == True --tbl_is_regular :: Table t -> Bool -- | Map f at table, padding short rows with k. tbl_make_regular :: (t -> u, u) -> Table t -> Table u -- | Append a sequence of nil (or default) values to each row of -- tbl so to make it regular (ie. all rows of equal length). tbl_make_regular_nil :: t -> Table t -> Table t -- | Matrix dimensions are written (rows,columns). type Dimensions i = (i, i) -- | Matrix indices are written (row,column) & are here _zero_ indexed. type Ix i = (i, i) -- | Translate Ix by row and column delta. -- --
-- ix_translate (1,2) (3,4) == (4,6) --ix_translate :: Num t => (t, t) -> Ix t -> Ix t -- | Modulo Ix by Dimensions. -- --
-- ix_modulo (4,4) (3,7) == (3,3) --ix_modulo :: Integral t => Dimensions t -> Ix t -> Ix t -- | Given number of columns and row index, list row indices. -- --
-- row_indices 3 1 == [(1,0),(1,1),(1,2)] --row_indices :: (Enum t, Num t) => t -> t -> [Ix t] -- | Given number of rows and column index, list column indices. -- --
-- column_indices_at 3 1 == [(0,1),(1,1),(2,1)] --column_indices_at :: (Enum t, Num t) => t -> t -> [Ix t] -- | All zero-indexed matrix indices, in row order. This is the order given -- by sort. -- --
-- matrix_indices (2,3) == [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)] -- sort (matrix_indices (2,3)) == matrix_indices (2,3) --matrix_indices :: (Enum t, Num t) => Dimensions t -> [Ix t] -- | Corner indices of given Dimensions, in row order. -- --
-- matrix_corner_indices (2,3) == [(0,0),(0,2),(1,0),(1,2)] --matrix_corner_indices :: Num t => Dimensions t -> [Ix t] -- | Parallelogram corner indices, given as rectangular Dimensions -- with an offset for the lower indices. -- --
-- parallelogram_corner_indices ((2,3),2) == [(0,0),(0,2),(1,2),(1,4)] --parallelogram_corner_indices :: Num t => (Dimensions t, t) -> [Ix t] -- | Apply ix_modulo and ix_translate for all -- matrix_indices, ie. all translations of a shape in row -- order. The resulting Ix sets are not sorted and may have -- duplicates. -- --
-- concat (all_ix_translations (2,3) [(0,0)]) == matrix_indices (2,3) --all_ix_translations :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]] -- | Sort sets into row order and remove duplicates. all_ix_translations_uniq :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]] -- | Map functions. module Music.Theory.Map -- | Erroring lookup. map_lookup_err :: Ord k => k -> Map k c -> c -- | flip of lookup. map_ix :: Ord k => Map k c -> k -> Maybe c -- | flip of map_lookup_err. map_ix_err :: Ord k => Map k c -> k -> c -- | IEE754 constants (c.f. Numeric.MathFunctions.Constants) module Music.Theory.Math.Constant -- | The smallest Double n such that 1 + n /= 1. epsilonValue :: Double -- | Largest representable finite value. largestFiniteValue :: Double -- | The smallest representable positive normalized value. smallestNormalizedValue :: Double -- | Specialised type conversions, see mk/mk-convert.hs -- --
-- map int_to_word8 [-1,0,255,256] == [255,0,255,0] -- map int_to_word8_maybe [-1,0,255,256] == [Nothing,Just 0,Just 255,Nothing] ---- --
-- map integer_to_int64_maybe [-2 ^ 63 - 1,2 ^ 63] == [Nothing,Nothing] -- map integer_to_word64_maybe [2 ^ 64 - 1,2 ^ 64] == [Just 18446744073709551615,Nothing] ---- --
-- map int16_to_float [-1,0,1] == [-1,0,1] --module Music.Theory.Math.Convert -- | Type specialised realToFrac real_to_float :: Real t => t -> Float -- | Type specialised realToFrac -- --
-- let n = sqrt (-1) in (n,real_to_double n) --real_to_double :: Real t => t -> Double -- | Type specialised realToFrac double_to_float :: Double -> Float -- | Type specialised realToFrac float_to_double :: Float -> Double double_to_word8 :: (Double -> Word8) -> Double -> Word8 -- | Type-specialise f, ie. round, ceiling, truncate -- --
-- map (double_to_int round) [0, 0.25 .. 1] == [0, 0, 0, 1, 1] -- map (double_to_int ceiling) [0, 0.25 .. 1] == [0, 1, 1, 1, 1] -- map (double_to_int floor) [0, 0.25 .. 1] == [0, 0, 0, 0, 1] -- map (double_to_int truncate) [0, 0.25 .. 1] == [0, 0, 0, 0, 1] --double_to_int :: (Double -> Int) -> Double -> Int -- | Type specialised fromIntegral int_to_rational :: Int -> Rational -- | Type specialised fromIntegral word8_to_word16 :: Word8 -> Word16 -- | Type specialised fromIntegral word8_to_word32 :: Word8 -> Word32 -- | Type specialised fromIntegral word8_to_word64 :: Word8 -> Word64 -- | Type specialised fromIntegral word8_to_int8 :: Word8 -> Int8 -- | Type specialised fromIntegral word8_to_int16 :: Word8 -> Int16 -- | Type specialised fromIntegral word8_to_int32 :: Word8 -> Int32 -- | Type specialised fromIntegral word8_to_int64 :: Word8 -> Int64 -- | Type specialised fromIntegral word8_to_int :: Word8 -> Int -- | Type specialised fromIntegral word8_to_integer :: Word8 -> Integer -- | Type specialised fromIntegral word8_to_float :: Word8 -> Float -- | Type specialised fromIntegral word8_to_double :: Word8 -> Double -- | Type specialised fromIntegral word16_to_word8 :: Word16 -> Word8 -- | Type specialised fromIntegral word16_to_word32 :: Word16 -> Word32 -- | Type specialised fromIntegral word16_to_word64 :: Word16 -> Word64 -- | Type specialised fromIntegral word16_to_int8 :: Word16 -> Int8 -- | Type specialised fromIntegral word16_to_int16 :: Word16 -> Int16 -- | Type specialised fromIntegral word16_to_int32 :: Word16 -> Int32 -- | Type specialised fromIntegral word16_to_int64 :: Word16 -> Int64 -- | Type specialised fromIntegral word16_to_int :: Word16 -> Int -- | Type specialised fromIntegral word16_to_integer :: Word16 -> Integer -- | Type specialised fromIntegral word16_to_float :: Word16 -> Float -- | Type specialised fromIntegral word16_to_double :: Word16 -> Double -- | Type specialised fromIntegral word32_to_word8 :: Word32 -> Word8 -- | Type specialised fromIntegral word32_to_word16 :: Word32 -> Word16 -- | Type specialised fromIntegral word32_to_word64 :: Word32 -> Word64 -- | Type specialised fromIntegral word32_to_int8 :: Word32 -> Int8 -- | Type specialised fromIntegral word32_to_int16 :: Word32 -> Int16 -- | Type specialised fromIntegral word32_to_int32 :: Word32 -> Int32 -- | Type specialised fromIntegral word32_to_int64 :: Word32 -> Int64 -- | Type specialised fromIntegral word32_to_int :: Word32 -> Int -- | Type specialised fromIntegral word32_to_integer :: Word32 -> Integer -- | Type specialised fromIntegral word32_to_float :: Word32 -> Float -- | Type specialised fromIntegral word32_to_double :: Word32 -> Double -- | Type specialised fromIntegral word64_to_word8 :: Word64 -> Word8 -- | Type specialised fromIntegral word64_to_word16 :: Word64 -> Word16 -- | Type specialised fromIntegral word64_to_word32 :: Word64 -> Word32 -- | Type specialised fromIntegral word64_to_int8 :: Word64 -> Int8 -- | Type specialised fromIntegral word64_to_int16 :: Word64 -> Int16 -- | Type specialised fromIntegral word64_to_int32 :: Word64 -> Int32 -- | Type specialised fromIntegral word64_to_int64 :: Word64 -> Int64 -- | Type specialised fromIntegral word64_to_int :: Word64 -> Int -- | Type specialised fromIntegral word64_to_integer :: Word64 -> Integer -- | Type specialised fromIntegral word64_to_float :: Word64 -> Float -- | Type specialised fromIntegral word64_to_double :: Word64 -> Double -- | Type specialised fromIntegral int8_to_word8 :: Int8 -> Word8 -- | Type specialised fromIntegral int8_to_word16 :: Int8 -> Word16 -- | Type specialised fromIntegral int8_to_word32 :: Int8 -> Word32 -- | Type specialised fromIntegral int8_to_word64 :: Int8 -> Word64 -- | Type specialised fromIntegral int8_to_int16 :: Int8 -> Int16 -- | Type specialised fromIntegral int8_to_int32 :: Int8 -> Int32 -- | Type specialised fromIntegral int8_to_int64 :: Int8 -> Int64 -- | Type specialised fromIntegral int8_to_int :: Int8 -> Int -- | Type specialised fromIntegral int8_to_integer :: Int8 -> Integer -- | Type specialised fromIntegral int8_to_float :: Int8 -> Float -- | Type specialised fromIntegral int8_to_double :: Int8 -> Double -- | Type specialised fromIntegral int16_to_word8 :: Int16 -> Word8 -- | Type specialised fromIntegral int16_to_word16 :: Int16 -> Word16 -- | Type specialised fromIntegral int16_to_word32 :: Int16 -> Word32 -- | Type specialised fromIntegral int16_to_word64 :: Int16 -> Word64 -- | Type specialised fromIntegral int16_to_int8 :: Int16 -> Int8 -- | Type specialised fromIntegral int16_to_int32 :: Int16 -> Int32 -- | Type specialised fromIntegral int16_to_int64 :: Int16 -> Int64 -- | Type specialised fromIntegral int16_to_int :: Int16 -> Int -- | Type specialised fromIntegral int16_to_integer :: Int16 -> Integer -- | Type specialised fromIntegral int16_to_float :: Int16 -> Float -- | Type specialised fromIntegral int16_to_double :: Int16 -> Double -- | Type specialised fromIntegral int32_to_word8 :: Int32 -> Word8 -- | Type specialised fromIntegral int32_to_word16 :: Int32 -> Word16 -- | Type specialised fromIntegral int32_to_word32 :: Int32 -> Word32 -- | Type specialised fromIntegral int32_to_word64 :: Int32 -> Word64 -- | Type specialised fromIntegral int32_to_int8 :: Int32 -> Int8 -- | Type specialised fromIntegral int32_to_int16 :: Int32 -> Int16 -- | Type specialised fromIntegral int32_to_int64 :: Int32 -> Int64 -- | Type specialised fromIntegral int32_to_int :: Int32 -> Int -- | Type specialised fromIntegral int32_to_integer :: Int32 -> Integer -- | Type specialised fromIntegral int32_to_float :: Int32 -> Float -- | Type specialised fromIntegral int32_to_double :: Int32 -> Double -- | Type specialised fromIntegral int64_to_word8 :: Int64 -> Word8 -- | Type specialised fromIntegral int64_to_word16 :: Int64 -> Word16 -- | Type specialised fromIntegral int64_to_word32 :: Int64 -> Word32 -- | Type specialised fromIntegral int64_to_word64 :: Int64 -> Word64 -- | Type specialised fromIntegral int64_to_int8 :: Int64 -> Int8 -- | Type specialised fromIntegral int64_to_int16 :: Int64 -> Int16 -- | Type specialised fromIntegral int64_to_int32 :: Int64 -> Int32 -- | Type specialised fromIntegral int64_to_int :: Int64 -> Int -- | Type specialised fromIntegral int64_to_integer :: Int64 -> Integer -- | Type specialised fromIntegral int64_to_float :: Int64 -> Float -- | Type specialised fromIntegral int64_to_double :: Int64 -> Double -- | Type specialised fromIntegral int_to_integral :: Integral i => Int -> i -- | Type specialised fromIntegral int_to_word8 :: Int -> Word8 -- | Type specialised fromIntegral int_to_word16 :: Int -> Word16 -- | Type specialised fromIntegral int_to_word32 :: Int -> Word32 -- | Type specialised fromIntegral int_to_word64 :: Int -> Word64 -- | Type specialised fromIntegral int_to_int8 :: Int -> Int8 -- | Type specialised fromIntegral int_to_int16 :: Int -> Int16 -- | Type specialised fromIntegral int_to_int32 :: Int -> Int32 -- | Type specialised fromIntegral int_to_int64 :: Int -> Int64 -- | Type specialised fromIntegral int_to_integer :: Int -> Integer -- | Type specialised fromIntegral int_to_float :: Int -> Float -- | Type specialised fromIntegral int_to_double :: Int -> Double -- | Type specialised fromIntegral integer_to_word8 :: Integer -> Word8 -- | Type specialised fromIntegral integer_to_word16 :: Integer -> Word16 -- | Type specialised fromIntegral integer_to_word32 :: Integer -> Word32 -- | Type specialised fromIntegral integer_to_word64 :: Integer -> Word64 -- | Type specialised fromIntegral integer_to_int8 :: Integer -> Int8 -- | Type specialised fromIntegral integer_to_int16 :: Integer -> Int16 -- | Type specialised fromIntegral integer_to_int32 :: Integer -> Int32 -- | Type specialised fromIntegral integer_to_int64 :: Integer -> Int64 -- | Type specialised fromIntegral integer_to_int :: Integer -> Int -- | Type specialised fromIntegral integer_to_float :: Integer -> Float -- | Type specialised fromIntegral integer_to_double :: Integer -> Double -- | Type specialised fromIntegral word8_to_word16_maybe :: Word8 -> Maybe Word16 -- | Type specialised fromIntegral word8_to_word32_maybe :: Word8 -> Maybe Word32 -- | Type specialised fromIntegral word8_to_word64_maybe :: Word8 -> Maybe Word64 -- | Type specialised fromIntegral word8_to_int8_maybe :: Word8 -> Maybe Int8 -- | Type specialised fromIntegral word8_to_int16_maybe :: Word8 -> Maybe Int16 -- | Type specialised fromIntegral word8_to_int32_maybe :: Word8 -> Maybe Int32 -- | Type specialised fromIntegral word8_to_int64_maybe :: Word8 -> Maybe Int64 -- | Type specialised fromIntegral word8_to_int_maybe :: Word8 -> Maybe Int -- | Type specialised fromIntegral word16_to_word8_maybe :: Word16 -> Maybe Word8 -- | Type specialised fromIntegral word16_to_word32_maybe :: Word16 -> Maybe Word32 -- | Type specialised fromIntegral word16_to_word64_maybe :: Word16 -> Maybe Word64 -- | Type specialised fromIntegral word16_to_int8_maybe :: Word16 -> Maybe Int8 -- | Type specialised fromIntegral word16_to_int16_maybe :: Word16 -> Maybe Int16 -- | Type specialised fromIntegral word16_to_int32_maybe :: Word16 -> Maybe Int32 -- | Type specialised fromIntegral word16_to_int64_maybe :: Word16 -> Maybe Int64 -- | Type specialised fromIntegral word16_to_int_maybe :: Word16 -> Maybe Int -- | Type specialised fromIntegral word32_to_word8_maybe :: Word32 -> Maybe Word8 -- | Type specialised fromIntegral word32_to_word16_maybe :: Word32 -> Maybe Word16 -- | Type specialised fromIntegral word32_to_word64_maybe :: Word32 -> Maybe Word64 -- | Type specialised fromIntegral word32_to_int8_maybe :: Word32 -> Maybe Int8 -- | Type specialised fromIntegral word32_to_int16_maybe :: Word32 -> Maybe Int16 -- | Type specialised fromIntegral word32_to_int32_maybe :: Word32 -> Maybe Int32 -- | Type specialised fromIntegral word32_to_int64_maybe :: Word32 -> Maybe Int64 -- | Type specialised fromIntegral word32_to_int_maybe :: Word32 -> Maybe Int -- | Type specialised fromIntegral word64_to_word8_maybe :: Word64 -> Maybe Word8 -- | Type specialised fromIntegral word64_to_word16_maybe :: Word64 -> Maybe Word16 -- | Type specialised fromIntegral word64_to_word32_maybe :: Word64 -> Maybe Word32 -- | Type specialised fromIntegral word64_to_int8_maybe :: Word64 -> Maybe Int8 -- | Type specialised fromIntegral word64_to_int16_maybe :: Word64 -> Maybe Int16 -- | Type specialised fromIntegral word64_to_int32_maybe :: Word64 -> Maybe Int32 -- | Type specialised fromIntegral word64_to_int64_maybe :: Word64 -> Maybe Int64 -- | Type specialised fromIntegral word64_to_int_maybe :: Word64 -> Maybe Int -- | Type specialised fromIntegral int8_to_word8_maybe :: Int8 -> Maybe Word8 -- | Type specialised fromIntegral int8_to_word16_maybe :: Int8 -> Maybe Word16 -- | Type specialised fromIntegral int8_to_word32_maybe :: Int8 -> Maybe Word32 -- | Type specialised fromIntegral int8_to_word64_maybe :: Int8 -> Maybe Word64 -- | Type specialised fromIntegral int8_to_int16_maybe :: Int8 -> Maybe Int16 -- | Type specialised fromIntegral int8_to_int32_maybe :: Int8 -> Maybe Int32 -- | Type specialised fromIntegral int8_to_int64_maybe :: Int8 -> Maybe Int64 -- | Type specialised fromIntegral int8_to_int_maybe :: Int8 -> Maybe Int -- | Type specialised fromIntegral int16_to_word8_maybe :: Int16 -> Maybe Word8 -- | Type specialised fromIntegral int16_to_word16_maybe :: Int16 -> Maybe Word16 -- | Type specialised fromIntegral int16_to_word32_maybe :: Int16 -> Maybe Word32 -- | Type specialised fromIntegral int16_to_word64_maybe :: Int16 -> Maybe Word64 -- | Type specialised fromIntegral int16_to_int8_maybe :: Int16 -> Maybe Int8 -- | Type specialised fromIntegral int16_to_int32_maybe :: Int16 -> Maybe Int32 -- | Type specialised fromIntegral int16_to_int64_maybe :: Int16 -> Maybe Int64 -- | Type specialised fromIntegral int16_to_int_maybe :: Int16 -> Maybe Int -- | Type specialised fromIntegral int32_to_word8_maybe :: Int32 -> Maybe Word8 -- | Type specialised fromIntegral int32_to_word16_maybe :: Int32 -> Maybe Word16 -- | Type specialised fromIntegral int32_to_word32_maybe :: Int32 -> Maybe Word32 -- | Type specialised fromIntegral int32_to_word64_maybe :: Int32 -> Maybe Word64 -- | Type specialised fromIntegral int32_to_int8_maybe :: Int32 -> Maybe Int8 -- | Type specialised fromIntegral int32_to_int16_maybe :: Int32 -> Maybe Int16 -- | Type specialised fromIntegral int32_to_int64_maybe :: Int32 -> Maybe Int64 -- | Type specialised fromIntegral int32_to_int_maybe :: Int32 -> Maybe Int -- | Type specialised fromIntegral int64_to_word8_maybe :: Int64 -> Maybe Word8 -- | Type specialised fromIntegral int64_to_word16_maybe :: Int64 -> Maybe Word16 -- | Type specialised fromIntegral int64_to_word32_maybe :: Int64 -> Maybe Word32 -- | Type specialised fromIntegral int64_to_word64_maybe :: Int64 -> Maybe Word64 -- | Type specialised fromIntegral int64_to_int8_maybe :: Int64 -> Maybe Int8 -- | Type specialised fromIntegral int64_to_int16_maybe :: Int64 -> Maybe Int16 -- | Type specialised fromIntegral int64_to_int32_maybe :: Int64 -> Maybe Int32 -- | Type specialised fromIntegral int64_to_int_maybe :: Int64 -> Maybe Int -- | Type specialised fromIntegral int_to_word8_maybe :: Int -> Maybe Word8 -- | Type specialised fromIntegral int_to_word16_maybe :: Int -> Maybe Word16 -- | Type specialised fromIntegral int_to_word32_maybe :: Int -> Maybe Word32 -- | Type specialised fromIntegral int_to_word64_maybe :: Int -> Maybe Word64 -- | Type specialised fromIntegral int_to_int8_maybe :: Int -> Maybe Int8 -- | Type specialised fromIntegral int_to_int16_maybe :: Int -> Maybe Int16 -- | Type specialised fromIntegral int_to_int32_maybe :: Int -> Maybe Int32 -- | Type specialised fromIntegral int_to_int64_maybe :: Int -> Maybe Int64 -- | Type specialised fromIntegral integer_to_word8_maybe :: Integer -> Maybe Word8 -- | Type specialised fromIntegral integer_to_word16_maybe :: Integer -> Maybe Word16 -- | Type specialised fromIntegral integer_to_word32_maybe :: Integer -> Maybe Word32 -- | Type specialised fromIntegral integer_to_word64_maybe :: Integer -> Maybe Word64 -- | Type specialised fromIntegral integer_to_int8_maybe :: Integer -> Maybe Int8 -- | Type specialised fromIntegral integer_to_int16_maybe :: Integer -> Maybe Int16 -- | Type specialised fromIntegral integer_to_int32_maybe :: Integer -> Maybe Int32 -- | Type specialised fromIntegral integer_to_int64_maybe :: Integer -> Maybe Int64 -- | Type specialised fromIntegral integer_to_int_maybe :: Integer -> Maybe Int -- | Math functions. module Music.Theory.Math -- | mod 5. mod5 :: Integral i => i -> i -- | mod 7. mod7 :: Integral i => i -> i -- | mod 12. mod12 :: Integral i => i -> i -- | mod 16. mod16 :: Integral i => i -> i -- | -- http://reference.wolfram.com/mathematica/ref/FractionalPart.html -- i.e. properFraction -- --
-- integral_and_fractional_parts 1.5 == (1,0.5) --integral_and_fractional_parts :: (Integral i, RealFrac t) => t -> (i, t) -- | Type specialised. integer_and_fractional_parts :: RealFrac t => t -> (Integer, t) -- | -- http://reference.wolfram.com/mathematica/ref/FractionalPart.html -- --
-- import Sound.SC3.Plot {- hsc3-plot -}
-- plot_p1_ln [map fractional_part [-2.0,-1.99 .. 2.0]]
--
fractional_part :: RealFrac a => a -> a
-- | floor of real_to_double.
real_floor :: (Real r, Integral i) => r -> i
-- | Type specialised real_floor.
real_floor_int :: Real r => r -> Int
-- | round of real_to_double.
real_round :: (Real r, Integral i) => r -> i
-- | Type specialised real_round.
real_round_int :: Real r => r -> Int
-- | Type specialised round
round_int :: RealFrac t => t -> Int
-- | Type-specialised fromIntegral
from_integral_to_int :: Integral i => i -> Int
-- | Type-specialised id
int_id :: Int -> Int
-- | Is r zero to k decimal places.
--
-- -- map (flip zero_to_precision 0.00009) [4,5] == [True,False] -- map (zero_to_precision 4) [0.00009,1.00009] == [True,False] --zero_to_precision :: Real r => Int -> r -> Bool -- | Is r whole to k decimal places. -- --
-- map (flip whole_to_precision 1.00009) [4,5] == [True,False] --whole_to_precision :: Real r => Int -> r -> Bool -- | http://reference.wolfram.com/mathematica/ref/SawtoothWave.html -- --
-- plot_p1_ln [map sawtooth_wave [-2.0,-1.99 .. 2.0]] --sawtooth_wave :: RealFrac a => a -> a -- | Predicate that is true if n/d can be simplified, ie. where -- gcd of n and d is not 1. -- --
-- map rational_simplifies [(2,3),(4,6),(5,7)] == [False,True,False] --rational_simplifies :: Integral a => (a, a) -> Bool -- | numerator and denominator of rational. rational_nd :: Integral t => Ratio t -> (t, t) -- | Rational as a whole number, or Nothing. rational_whole :: Integral a => Ratio a -> Maybe a -- | Erroring variant. rational_whole_err :: Integral a => Ratio a -> a -- | Sum of numerator & denominator. ratio_nd_sum :: Integral t => Ratio t -> t -- | Is n a whole (integral) value. -- --
-- map real_is_whole [-1.0,-0.5,0.0,0.5,1.0] == [True,False,True,False,True] --real_is_whole :: Real n => n -> Bool -- | fromInteger . floor. floor_f :: (RealFrac a, Num b) => a -> b -- | Round b to nearest multiple of a. -- --
-- map (round_to 0.25) [0,0.1 .. 1] == [0.0,0.0,0.25,0.25,0.5,0.5,0.5,0.75,0.75,1.0,1.0] -- map (round_to 25) [0,10 .. 100] == [0,0,25,25,50,50,50,75,75,100,100] --round_to :: RealFrac n => n -> n -> n -- | Variant of recip that checks input for zero. -- --
-- map recip [1,1/2,0,-1] -- map recip_m [1,1/2,0,-1] == [Just 1,Just 2,Nothing,Just (-1)] --recip_m :: (Eq a, Fractional a) => a -> Maybe a -- | One-indexed mod function. -- --
-- map (`oi_mod` 5) [1..10] == [1,2,3,4,5,1,2,3,4,5] --oi_mod :: Integral a => a -> a -> a -- | One-indexed divMod function. -- --
-- map (`oi_divMod` 5) [1,3 .. 9] == [(0,1),(0,3),(0,5),(1,2),(1,4)] --oi_divMod :: Integral t => t -> t -> (t, t) -- | Integral square root (sqrt) function. -- --
-- map i_square_root [0,1,4,9,16,25,36,49,64,81,100] == [0 .. 10] -- map i_square_root [4 .. 16] == [2,2,2,2,2,3,3,3,3,3,3,3,4] --i_square_root :: Integral t => t -> t -- | (0,1) = {x | 0 < x < 1} in_open_interval :: Ord a => (a, a) -> a -> Bool -- |
-- 12 `nth_root` 2 == 1.0594630943592953 --nth_root :: (Floating a, Eq a) => a -> a -> a -- | Arithmetic mean (average) of a list. -- --
-- map arithmetic_mean [[-3..3],[0..5],[1..5],[3,5,7],[7,7],[3,9,10,11,12]] == [0,2.5,3,5,7,9] --arithmetic_mean :: Fractional a => [a] -> a -- | Numerically stable mean -- --
-- map ns_mean [[-3..3],[0..5],[1..5],[3,5,7],[7,7],[3,9,10,11,12]] == [0,2.5,3,5,7,9] --ns_mean :: Floating a => [a] -> a -- | Square of n. -- --
-- square 5 == 25 --square :: Num a => a -> a -- | The totient function phi(n), also called Euler's totient function. -- --
-- import Sound.SC3.Plot {- hsc3-plot -}
-- plot_p1_stp [map totient [1::Int .. 100]]
--
totient :: Integral i => i -> i
-- | The n-th order Farey sequence.
--
-- -- farey 1 == [0, 1] -- farey 2 == [0, 1/2, 1] -- farey 3 == [0, 1/3, 1/2, 2/3, 1] -- farey 4 == [0, 1/4, 1/3, 1/2, 2/3, 3/4, 1] -- farey 5 == [0, 1/5,1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4,4/5, 1] -- farey 6 == [0, 1/6,1/5,1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4,4/5,5/6, 1] -- farey 7 == [0, 1/7,1/6,1/5,1/4,2/7,1/3, 2/5,3/7,1/2,4/7,3/5, 2/3,5/7,3/4,4/5,5/6,6/7, 1] -- farey 8 == [0,1/8,1/7,1/6,1/5,1/4,2/7,1/3,3/8,2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4,4/5,5/6,6/7,7/8,1] --farey :: Integral i => i -> [Ratio i] -- | The length of the n-th order Farey sequence. -- --
-- map farey_length [1 .. 12] == [2,3,5,7,11,13,19,23,29,33,43,47] -- map (length . farey) [1 .. 12] == map farey_length [1 .. 12] --farey_length :: Integral i => i -> i -- | Function to generate the Stern-Brocot tree from an initial row. -- % normalises so 1/0 cannot be written as a Rational, -- hence (n,d). stern_brocot_tree_f :: Num n => [(n, n)] -> [[(n, n)]] -- | The Stern-Brocot tree from (01,10). -- --
-- let t = stern_brocot_tree -- t !! 0 == [(0,1),(1,0)] -- t !! 1 == [(0,1),(1,1),(1,0)] -- t !! 2 == [(0,1),(1,2),(1,1),(2,1),(1,0)] -- t !! 3 == [(0,1),(1,3),(1,2),(2,3),(1,1),(3,2),(2,1),(3,1),(1,0)] ---- --
-- map length (take 12 stern_brocot_tree) == [2,3,5,9,17,33,65,129,257,513,1025,2049] -- A000051 --stern_brocot_tree :: Num n => [[(n, n)]] -- | Left-hand (rational) side of the the Stern-Brocot tree, ie, from -- (01,11). stern_brocot_tree_lhs :: Num n => [[(n, n)]] -- | stern_brocot_tree_f as Ratios, for finite subsets. -- --
-- let t = stern_brocot_tree_f_r [0,1] -- t !! 1 == [0,1/2,1] -- t !! 2 == [0,1/3,1/2,2/3,1] -- t !! 3 == [0,1/4,1/3,2/5,1/2,3/5,2/3,3/4,1] -- t !! 4 == [0,1/5,1/4,2/7,1/3,3/8,2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4,4/5,1] --stern_brocot_tree_f_r :: Integral n => [Ratio n] -> [[Ratio n]] -- | Outer product of vectors represented as lists, c.f. liftM2 -- --
-- outer_product (*) [2..5] [2..5] == [[4,6,8,10],[6,9,12,15],[8,12,16,20],[10,15,20,25]] -- liftM2 (*) [2..5] [2..5] == [4,6,8,10,6,9,12,15,8,12,16,20,10,15,20,25] --outer_product :: (a -> b -> c) -> [a] -> [b] -> [[c]] -- | c.f. Statistics.Sample.Histogram (this is much slower but doesn't -- require any libraries) module Music.Theory.Math.Histogram -- | Calculate histogram on numBins places. Returns the range of each bin -- and the number of elements in each. -- --
-- map (snd . bHistogram 10) [[1 .. 10],[1,1,1,2,2,3,10]] == [[1,1,1,1,1,1,1,1,1,1],[3,2,1,0,0,0,0,0,0,1]] --bHistogram :: Int -> [Double] -> ([(Double, Double)], [Int]) -- | Calculate range. -- --
-- bHistogramRange 10 (replicate 10 1) == (0.9, 1.1) -- bHistogramRange 10 (replicate 10 0) == (-1, 1) -- bHistogramRange 10 [1 .. 10] == (0.5, 10.5) -- bHistogramRange 25 [1 .. 10] == (0.8125,10.1875) --bHistogramRange :: Int -> [Double] -> (Double, Double) -- | Extensions to Data.Maybe. module Music.Theory.Maybe -- | Variant with error text. from_just :: String -> Maybe a -> a -- | Variant of unzip. -- --
-- let r = ([Just 1,Nothing,Just 3],[Just 'a',Nothing,Just 'c']) -- in maybe_unzip [Just (1,'a'),Nothing,Just (3,'c')] == r --maybe_unzip :: [Maybe (a, b)] -> ([Maybe a], [Maybe b]) -- | Replace Nothing elements with last Just value. This does -- not alter the length of the list. -- --
-- maybe_latch 1 [Nothing,Just 2,Nothing,Just 4] == [1,2,2,4] --maybe_latch :: a -> [Maybe a] -> [a] -- | Variant requiring initial value is not Nothing. -- --
-- maybe_latch1 [Just 1,Nothing,Nothing,Just 4] == [1,1,1,4] --maybe_latch1 :: [Maybe a] -> [a] -- | map of fmap. -- --
-- maybe_map negate [Nothing,Just 2] == [Nothing,Just (-2)] --maybe_map :: (a -> b) -> [Maybe a] -> [Maybe b] -- | If either is Nothing then False, else eq of -- values. maybe_eq_by :: (t -> u -> Bool) -> Maybe t -> Maybe u -> Bool -- | Join two values, either of which may be missing. maybe_join' :: (s -> t) -> (s -> s -> t) -> Maybe s -> Maybe s -> Maybe t -- | maybe_join' of id maybe_join :: (t -> t -> t) -> Maybe t -> Maybe t -> Maybe t -- | Apply predicate inside Maybe. -- --
-- maybe_predicate even (Just 3) == Nothing --maybe_predicate :: (a -> Bool) -> Maybe a -> Maybe a -- | map of maybe_predicate. -- --
-- let r = [Nothing,Nothing,Nothing,Just 4] -- in maybe_filter even [Just 1,Nothing,Nothing,Just 4] == r --maybe_filter :: (a -> Bool) -> [Maybe a] -> [Maybe a] -- | Variant of catMaybes. If all elements of the list are Just -- a, then gives Just [a] else gives Nothing. -- --
-- all_just (map Just [1..3]) == Just [1..3] -- all_just [Just 1,Nothing,Just 3] == Nothing --all_just :: [Maybe a] -> Maybe [a] -- | Monad functions. module Music.Theory.Monad -- | sequence_ of repeat. repeatM_ :: Monad m => m a -> m () -- | Monadic variant of iterate. iterateM_ :: Monad m => (st -> m st) -> st -> m () -- | fmap of concat of mapM concatMapM :: (Functor m, Monad m) => (t -> m [u]) -> [t] -> m [u] -- | If i then j else k. m_if :: Monad m => (m Bool, m t, m t) -> m t -- | Directory functions. module Music.Theory.Directory -- | takeDirectory gives different answers depending on whether -- there is a trailing separator. -- --
-- x = ["x/y","x/y/","x","/"] -- map parent_dir x == ["x","x",".","/"] -- map takeDirectory x == ["x","x/y",".","/"] --parent_dir :: FilePath -> FilePath -- | Colon separated path list. path_split :: String -> [FilePath] -- | Read environment variable and split path. Error if enviroment variable -- not set. -- --
-- path_from_env "PATH" -- path_from_env "NONPATH" -- error --path_from_env :: String -> IO [FilePath] -- | Expand a path to include all subdirectories recursively. -- --
-- p = ["/home/rohan/sw/hmt-base/Music", "/home/rohan/sw/hmt/Music"] -- r <- path_recursive p -- length r == 44 --path_recursive :: [FilePath] -> IO [FilePath] -- | Scan a list of directories until a file is located, or not. Stop once -- a file is located, do not traverse any sub-directory structure. -- --
-- mapM (path_scan ["/sbin","/usr/bin"]) ["fsck","ghc"] --path_scan :: [FilePath] -> FilePath -> IO (Maybe FilePath) -- | Erroring variant. path_scan_err :: [FilePath] -> FilePath -> IO FilePath -- | Scan a list of directories and return all located files. Do not -- traverse any sub-directory structure. Since 1.2.1.0 there is also -- findFiles. -- --
-- let path = ["/home/rohan/sw/hmt-base","/home/rohan/sw/hmt"] -- path_search path "README.md" -- findFiles path "README.md" --path_search :: [FilePath] -> FilePath -> IO [FilePath] -- | Get sorted list of files at dir with ext, ie. ls -- dir/*.ext -- --
-- dir_list_ext "/home/rohan/rd/j/" ".hs" --dir_list_ext :: FilePath -> String -> IO [FilePath] -- | Post-process dir_list_ext to gives file-names with dir -- prefix. -- --
-- dir_list_ext_path "/home/rohan/rd/j/" ".hs" --dir_list_ext_path :: FilePath -> String -> IO [FilePath] -- | Subset of files in dir with an extension in ext. -- Extensions include the leading dot and are case-sensitive. Results are -- relative to dir. dir_subset_rel :: [String] -> FilePath -> IO [FilePath] -- | Variant of dir_subset_rel where results have dir/ prefix. -- --
-- dir_subset [".hs"] "/home/rohan/sw/hmt/cmd" --dir_subset :: [String] -> FilePath -> IO [FilePath] -- | Subdirectories (relative) of dir. dir_subdirs_rel :: FilePath -> IO [FilePath] -- | Subdirectories of dir. dir_subdirs :: FilePath -> IO [FilePath] -- | Recursive form of dir_subdirs. -- --
-- dir_subdirs_recursively "/home/rohan/sw/hmt-base/Music" --dir_subdirs_recursively :: FilePath -> IO [FilePath] -- | If path is not absolute, prepend current working directory. -- --
-- to_absolute_cwd "x" --to_absolute_cwd :: FilePath -> IO FilePath -- | If i is an existing file then j else k. if_file_exists :: (FilePath, IO t, IO t) -> IO t -- | createDirectoryIfMissing (including parents) and then -- writeFile writeFile_mkdir :: FilePath -> String -> IO () -- | writeFile_mkdir only if file does not exist. writeFile_mkdir_x :: FilePath -> String -> IO () -- | Ordering functions module Music.Theory.Ord -- | Minimum by f. min_by :: Ord a => (t -> a) -> t -> t -> t -- | Specialised fromEnum. ord_to_int :: Ordering -> Int -- | Specialised toEnum. int_to_ord :: Int -> Ordering -- | Invert Ordering. -- --
-- map ord_invert [LT,EQ,GT] == [GT,EQ,LT] --ord_invert :: Ordering -> Ordering -- | Given Ordering, re-order pair, order_pair :: Ordering -> (t, t) -> (t, t) -- | Sort a pair of equal type values using given comparison function. -- --
-- sort_pair compare ('b','a') == ('a','b')
--
sort_pair :: (t -> t -> Ordering) -> (t, t) -> (t, t)
-- | Variant where the comparison function may not compute a value.
sort_pair_m :: (t -> t -> Maybe Ordering) -> (t, t) -> Maybe (t, t)
-- | Permutation functions.
module Music.Theory.Permutations
-- | Factorial function.
--
-- -- (factorial 20,maxBound::Int) --factorial :: Integral n => n -> n -- | Number of k element permutations of a set of n elements. -- --
-- let f = nk_permutations in (f 3 2,f 3 3,f 4 3,f 4 4,f 13 3,f 12 12) == (6,6,24,24,1716,479001600) --nk_permutations :: Integral a => a -> a -> a -- | Number of nk permutations where n == k. -- --
-- map n_permutations [1..8] == [1,2,6,24,120,720,5040,40320] -- n_permutations 12 == 479001600 -- n_permutations 16 `div` 1000000 == 20922789 --n_permutations :: Integral a => a -> a -- | Permutation given as a zero-indexed list of destination indices. type Permutation = [Int] -- | Generate the permutation from p to q, ie. the -- permutation that, when applied to p, gives q. -- --
-- p = permutation "abc" "bac" -- p == [1,0,2] -- apply_permutation p "abc" == "bac" --permutation :: Eq t => [t] -> [t] -> Permutation -- | Permutation to list of swaps, ie. zip [0..] -- --
-- permutation_to_swaps [0,2,1,3] == [(0,0),(1,2),(2,1),(3,3)] --permutation_to_swaps :: Permutation -> [(Int, Int)] -- | Inverse of permutation_to_swaps, ie. map snd -- . sort swaps_to_permutation :: [(Int, Int)] -> Permutation -- | List of cycles to list of swaps. -- --
-- cycles_to_swaps [[0,2],[1],[3,4]] == [(0,2),(1,1),(2,0),(3,4),(4,3)] --cycles_to_swaps :: [[Int]] -> [(Int, Int)] swaps_to_cycles :: [(Int, Int)] -> [[Int]] -- | Apply permutation f to p. -- --
-- let p = permutation [1..4] [4,3,2,1] -- p == [3,2,1,0] -- apply_permutation p [1..4] == [4,3,2,1] --apply_permutation :: Permutation -> [t] -> [t] -- | Composition of apply_permutation and -- from_cycles_zero_indexed. -- --
-- apply_permutation_c_zero_indexed [[0,3],[1,2]] [1..4] == [4,3,2,1] -- apply_permutation_c_zero_indexed [[0,2],[1],[3,4]] [1..5] == [3,2,1,5,4] -- apply_permutation_c_zero_indexed [[0,1,4],[2,3]] [1..5] == [2,5,4,3,1] -- apply_permutation_c_zero_indexed [[0,1,3],[2,4]] [1..5] == [2,4,5,1,3] --apply_permutation_c_zero_indexed :: [[Int]] -> [a] -> [a] p_inverse :: Permutation -> Permutation p_cycles :: Permutation -> [[Int]] -- | True if the inverse of p is p. -- --
-- non_invertible [1,0,2] == True -- non_invertible [2,7,4,9,8,3,5,0,6,1] == False ---- --
-- let p = permutation [1..4] [4,3,2,1] -- non_invertible p == True && p_cycles p == [[0,3],[1,2]] --non_invertible :: Permutation -> Bool -- | Generate a permutation from the cycles c (zero-indexed) -- --
-- apply_permutation (from_cycles_zero_indexed [[0,1,2,3]]) [1..4] == [2,3,4,1] --from_cycles_zero_indexed :: [[Int]] -> Permutation from_cycles_one_indexed :: [[Int]] -> Permutation -- | Generate all permutations of size n (naive) -- --
-- let r = [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] -- map one_line (permutations_n 3) == r --permutations_n :: Int -> [Permutation] p_size :: Permutation -> Int -- | Composition of q then p. -- --
-- let p = from_cycles_zero_indexed [[0,2],[1],[3,4]] -- let q = from_cycles_zero_indexed [[0,1,4],[2,3]] -- let r = p `compose` q -- apply_permutation r [1,2,3,4,5] == [2,4,5,1,3] --compose :: Permutation -> Permutation -> Permutation -- | One-indexed p_cycles cycles_one_indexed :: Permutation -> [[Int]] -- | flip of compose -- --
-- cycles_one_indexed (from_cycles_one_indexed [[1,5],[2,3,6],[4]] `permutation_mul` from_cycles_one_indexed [[1,6,4],[2],[3,5]]) --permutation_mul :: Permutation -> Permutation -> Permutation -- | Two line notation of p. -- --
-- two_line (permutation [0,1,3] [1,0,3]) == ([1,2,3],[2,1,3]) --two_line :: Permutation -> ([Int], [Int]) -- | One line notation of p. -- --
-- one_line (permutation [0,1,3] [1,0,3]) == [2,1,3] ---- --
-- let r = [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] -- map one_line (permutations_n 3) == r --one_line :: Permutation -> [Int] -- | Variant of one_line that produces a compact string. -- --
-- one_line_compact (permutation [0,1,3] [1,0,3]) == "213" ---- --
-- let p = permutations_n 3 -- unwords (map one_line_compact p) == "123 132 213 231 312 321" --one_line_compact :: Permutation -> String -- | Multiplication table of symmetric group n. -- --
-- unlines (map (unwords . map one_line_compact) (multiplication_table 3)) ---- --
-- ==> 123 132 213 231 312 321 -- 132 123 312 321 213 231 -- 213 231 123 132 321 312 -- 231 213 321 312 123 132 -- 312 321 132 123 231 213 -- 321 312 231 213 132 123 --multiplication_table :: Int -> [[Permutation]] -- | Combination functions. module Music.Theory.Combinations -- | Number of k element combinations of a set of n elements. -- --
-- map (uncurry nk_combinations) [(4,2),(5,3),(6,3),(13,3)] == [6,10,20,286] --nk_combinations :: Integral a => a -> a -> a -- | k element subsets of s. -- --
-- combinations 3 [1..4] == [[1,2,3],[1,2,4],[1,3,4],[2,3,4]] -- length (combinations 3 [1..5]) == nk_combinations 5 3 -- combinations 3 "xyzw" == ["xyz","xyw","xzw","yzw"] --combinations :: Int -> [a] -> [[a]] -- | http://www.acta.sapientia.ro/acta-info/C1-1/info1-9.pdf (P.110) -- --
-- dyck_words_lex 3 == [[0,0,0,1,1,1],[0,0,1,0,1,1],[0,0,1,1,0,1],[0,1,0,0,1,1],[0,1,0,1,0,1]] --dyck_words_lex :: (Num t, Ord t) => t -> [[t]] -- | Translate 01 to []. -- --
-- unwords (map dyck_word_to_str (dyck_words_lex 3)) == "[[[]]] [[][]] [[]][] [][[]] [][][]" --dyck_word_to_str :: Integral n => [n] -> [Char] -- | Translate [] to 01 dyck_word_from_str :: Integral n => [Char] -> [n] -- | Is x a segment of a lattice word. is_lattice_segment :: Integral n => [n] -> Bool -- | Is x a lattice word. -- -- is_lattice_word [1,1,1,2,2,1,2,1] == True is_lattice_word :: Integral n => [n] -> Bool -- | is_lattice_word of reverse. is_yamanouchi_word :: Integral n => [n] -> Bool -- | is_lattice_word of dyck_word_from_str -- --
-- is_dyck_word "[][[][[[][]]]]" == True --is_dyck_word :: String -> Bool -- | Read functions. module Music.Theory.Read -- | Transform ReadS function into precise Read function. -- Requires using all the input to produce a single token. The only -- exception is a singular trailing white space character. reads_to_read_precise :: ReadS t -> String -> Maybe t -- | Error variant of reads_to_read_precise. reads_to_read_precise_err :: String -> ReadS t -> String -> t -- | reads_to_read_precise of reads. -- --
-- read_maybe "1.0" :: Maybe Int -- read_maybe "1.0" :: Maybe Float --read_maybe :: Read a => String -> Maybe a -- | Variant of read_maybe with default value. -- --
-- map (read_def 0) ["2","2:","2\n"] == [2,0,2] --read_def :: Read a => a -> String -> a -- | Variant of read_maybe that errors on Nothing, printing -- message. read_err_msg :: Read a => String -> String -> a -- | Default message. read_err :: Read a => String -> a -- | Variant of reads requiring exact match, no trailing white -- space. -- --
-- map reads_exact ["1.5","2,5"] == [Just 1.5,Nothing] --reads_exact :: Read a => String -> Maybe a -- | Variant of reads_exact that errors on failure. reads_exact_err :: Read a => String -> String -> a -- | Allow commas as thousand separators. -- --
-- let r = [Just 123456,Just 123456,Nothing,Just 123456789] -- map read_integral_allow_commas_maybe ["123456","123,456","1234,56","123,456,789"] == r --read_integral_allow_commas_maybe :: Read i => String -> Maybe i read_integral_allow_commas_err :: (Integral i, Read i) => String -> i -- | Type specialised. -- --
-- map read_int_allow_commas ["123456","123,456","123,456,789"] == [123456,123456,123456789] --read_int_allow_commas :: String -> Int -- | Read a ratio where the division is given by / instead of -- % and the integers allow commas. -- --
-- map read_ratio_with_div_err ["123,456/7","123,456,789"] == [123456/7,123456789] --read_ratio_with_div_err :: (Integral i, Read i) => String -> Ratio i -- | Read Ratio, allow commas for thousand separators. -- --
-- read_ratio_allow_commas_err "327,680" "177,147" == 327680 / 177147 --read_ratio_allow_commas_err :: (Integral i, Read i) => String -> String -> Ratio i -- | Delete trailing ., read fails for 700.. delete_trailing_point :: String -> String -- | read_err disallows trailing decimal points. -- --
-- map read_fractional_allow_trailing_point_err ["123.","123.4"] == [123.0,123.4] --read_fractional_allow_trailing_point_err :: Read n => String -> n -- | Type specialised read_maybe. -- --
-- map read_maybe_int ["2","2:","2\n","x"] == [Just 2,Nothing,Just 2,Nothing] --read_maybe_int :: String -> Maybe Int -- | Type specialised read_err. read_int :: String -> Int -- | Type specialised read_maybe. read_maybe_double :: String -> Maybe Double -- | Type specialised read_err. read_double :: String -> Double -- | Type specialised read_maybe. -- --
-- map read_maybe_rational ["1","1%2","1/2"] == [Nothing,Just (1/2),Nothing] --read_maybe_rational :: String -> Maybe Rational -- | Type specialised read_err. -- --
-- read_rational "1%4" --read_rational :: String -> Rational -- | Read binary integer. -- --
-- mapMaybe read_bin (words "000 001 010 011 100 101 110 111") == [0 .. 7] --read_bin :: Integral a => String -> Maybe a -- | Erroring variant. read_bin_err :: Integral a => String -> a -- | Error variant of readHex. -- --
-- read_hex_err "F0B0" == 61616 --read_hex_err :: (Eq n, Integral n) => String -> n -- | Read hex value from string of at most k places. read_hex_sz :: (Eq n, Integral n) => Int -> String -> n -- | Read hexadecimal representation of 32-bit unsigned word. -- --
-- map read_hex_word32 ["00000000","12345678","FFFFFFFF"] == [minBound,305419896,maxBound] --read_hex_word32 :: String -> Word32 -- | Parser for rational_pp. -- --
-- map rational_parse ["1","3/2","5/4","2"] == [1,3/2,5/4,2] -- rational_parse "" == undefined --rational_parse :: (Read t, Integral t) => String -> Ratio t -- | Very simple command line interface option parser. -- -- Only allows options of the form --key=value, with the form --key equal -- to --key=True. -- -- A list of OptUsr describes the options and provides default values. -- -- get_opt_arg merges user and default values into a table with -- values for all options. -- -- To fetch options use opt_get and opt_read. module Music.Theory.Opt -- | (Key,Value) -- -- Key does not include leading '--'. type Opt = (String, String) -- | (Key,Default-Value,Type,Note) type OptUsr = (String, String, String, String) -- | Re-write default values at OptUsr. opt_usr_rw_def :: [Opt] -> [OptUsr] -> [OptUsr] -- | OptUsr to Opt. opt_plain :: OptUsr -> Opt -- | OptUsr to help string, indent is two spaces. opt_usr_help :: OptUsr -> String -- | unlines of opt_usr_help opt_help :: [OptUsr] -> String -- | Lookup Key in Opt, error if non-existing. opt_get :: [Opt] -> String -> String -- | Variant that returns Nothing if the result is the empty string, else -- Just the result. opt_get_nil :: [Opt] -> String -> Maybe String -- | read of get_opt opt_read :: Read t => [Opt] -> String -> t -- | Parse k or k=v string, else error. opt_param_parse :: String -> Opt -- | Parse option string of form "--opt" or "--key=value". -- --
-- opt_parse "--opt" == Just ("opt","True")
-- opt_parse "--key=value" == Just ("key","value")
--
opt_parse :: String -> Maybe Opt
-- | Parse option sequence, collating options and non-options.
--
--
-- opt_set_parse (words "--a --b=c d") == ([("a","True"),("b","c")],["d"])
--
opt_set_parse :: [String] -> ([Opt], [String])
-- | Left-biased Opt merge.
opt_merge :: [Opt] -> [Opt] -> [Opt]
-- | Process argument list.
opt_proc :: [OptUsr] -> [String] -> ([Opt], [String])
-- | Usage text
type OptHelp = [String]
-- | Format usage pre-amble and opt_help.
opt_help_pp :: OptHelp -> [OptUsr] -> String
-- | Print help and exit.
opt_usage :: OptHelp -> [OptUsr] -> IO ()
-- | Print help and error.
opt_error :: OptHelp -> [OptUsr] -> t
-- | Verify that all Opt have keys that are in OptUsr
opt_verify :: OptHelp -> [OptUsr] -> [Opt] -> IO ()
-- | opt_set_parse and maybe opt_verify and opt_merge
-- of getArgs. If arguments include -h or --help run
-- opt_usage
opt_get_arg :: Bool -> OptHelp -> [OptUsr] -> IO ([Opt], [String])
-- | Parse param set, one parameter per line.
--
--
-- opt_param_set_parse "a\nb=c" == [("a","True"),("b","c")]
--
opt_param_set_parse :: String -> [Opt]
-- | Simple scanner over argument list.
opt_scan :: [String] -> String -> Maybe String
-- | Scanner with default value.
opt_scan_def :: [String] -> (String, String) -> String
-- | Reading scanner with default value.
opt_scan_read :: Read t => [String] -> (String, t) -> t
-- | Byte functions.
module Music.Theory.Byte
-- | toEnum of word8_to_int
word8_to_enum :: Enum e => Word8 -> e
-- | int_to_word8_maybe of fromEnum
enum_to_word8 :: Enum e => e -> Maybe Word8
-- | Type-specialised word8_to_enum
--
-- -- map word8_to_char [60,62] == "<>" --word8_to_char :: Word8 -> Char -- | int_to_word8 of fromEnum char_to_word8 :: Char -> Word8 -- | int_to_word8 of digitToInt digit_to_word8 :: Char -> Word8 -- | intToDigit of word8_to_int word8_to_digit :: Word8 -> Char -- | at of word8_to_int word8_at :: [t] -> Word8 -> t -- | Given n in (0,255) make two character hex string. -- --
-- mapMaybe byte_hex_pp [0x0F,0xF0,0xF0F] == ["0F","F0"] --byte_hex_pp :: (Integral i, Show i) => i -> Maybe String -- | Erroring variant. byte_hex_pp_err :: (Integral i, Show i) => i -> String -- | byte_hex_pp_err either plain (ws = False) or with spaces (ws = -- True). Plain is the same format written by xxd -p and read by xxd -r -- -p. -- --
-- byte_seq_hex_pp True [0x0F,0xF0] == "0F F0" --byte_seq_hex_pp :: (Integral i, Show i) => Bool -> [i] -> String -- | Read two character hexadecimal string. -- --
-- mapMaybe read_hex_byte (Split.chunksOf 2 "0FF0F") == [0x0F,0xF0] --read_hex_byte :: (Eq t, Integral t) => String -> Maybe t -- | Erroring variant. read_hex_byte_err :: (Eq t, Integral t) => String -> t -- | Sequence of read_hex_byte_err -- --
-- read_hex_byte_seq "000FF0FF" == [0x00,0x0F,0xF0,0xFF] --read_hex_byte_seq :: (Eq t, Integral t) => String -> [t] -- | Variant that filters white space. -- --
-- read_hex_byte_seq_ws "00 0F F0 FF" == [0x00,0x0F,0xF0,0xFF] --read_hex_byte_seq_ws :: (Eq t, Integral t) => String -> [t] -- | Load binary U8 sequence from file. load_byte_seq :: Integral i => FilePath -> IO [i] -- | Store binary U8 sequence to file. store_byte_seq :: Integral i => FilePath -> [i] -> IO () -- | Load hexadecimal text U8 sequences from file. load_hex_byte_seq :: Integral i => FilePath -> IO [[i]] -- | Store U8 sequences as hexadecimal text, one sequence per -- line. store_hex_byte_seq :: (Integral i, Show i) => FilePath -> [[i]] -> IO () castFloatToWord32 :: Float -> Word32 castWord32ToFloat :: Word32 -> Float castDoubleToWord64 :: Double -> Word64 castWord64ToDouble :: Word64 -> Double -- | Show functions. module Music.Theory.Show -- | Show positive and negative values always with sign, maybe show zero, -- maybe right justify. -- --
-- map (num_diff_str_opt (True,2)) [-2,-1,0,1,2] == ["-2","-1"," 0","+1","+2"] --num_diff_str_opt :: (Ord a, Num a, Show a) => (Bool, Int) -> a -> String -- | Show only positive and negative values, always with sign. -- --
-- map num_diff_str [-2,-1,0,1,2] == ["-2","-1","","+1","+2"] -- map show [-2,-1,0,1,2] == ["-2","-1","0","1","2"] --num_diff_str :: (Num a, Ord a, Show a) => a -> String -- | Pretty printer for Rational using / and eliding -- denominators of 1. -- --
-- map rational_pp [1,3/2,5/4,2] == ["1","3/2","5/4","2"] --rational_pp :: (Show a, Integral a) => Ratio a -> String -- | Pretty print ratio as : separated integers, if nil is -- True elide unit denominator. -- --
-- map (ratio_pp_opt True) [1,3/2,2] == ["1","3:2","2"] --ratio_pp_opt :: Bool -> Rational -> String -- | Pretty print ratio as : separated integers. -- --
-- map ratio_pp [1,3/2,2] == ["1:1","3:2","2:1"] --ratio_pp :: Rational -> String -- | Show rational to n decimal places. -- --
-- let r = approxRational pi 1e-100 -- r == 884279719003555 / 281474976710656 -- show_rational_decimal 12 r == "3.141592653590" -- show_rational_decimal 3 (-100) == "-100.000" --show_rational_decimal :: Int -> Rational -> String -- | Show r as float to k places. -- --
-- real_pp 4 (1/3 :: Rational) == "0.3333" -- map (real_pp 4) [1,1.1,1.12,1.123,1.1234,1/0,sqrt (-1)] --real_pp :: Real t => Int -> t -> String -- | Variant that writes ∞ for Infinity. -- --
-- putStrLn $ unwords $ map (real_pp_unicode 4) [1/0,-1/0] --real_pp_unicode :: Real t => Int -> t -> [Char] -- | Prints n as integral or to at most k decimal places. -- Does not print -0. -- --
-- real_pp_trunc 4 (1/3 :: Rational) == "0.3333" -- map (real_pp_trunc 4) [1,1.1,1.12,1.123,1.1234] == ["1","1.1","1.12","1.123","1.1234"] -- map (real_pp_trunc 4) [1.00009,1.00001] == ["1.0001","1"] -- map (real_pp_trunc 2) [59.999,60.001,-0.00,-0.001] --real_pp_trunc :: Real t => Int -> t -> String -- | Variant of showFFloat. The Show instance for floats -- resorts to exponential notation very readily. -- --
-- [show 0.01,realfloat_pp 2 0.01] == ["1.0e-2","0.01"] -- map (realfloat_pp 4) [1,1.1,1.12,1.123,1.1234,1/0,sqrt (-1)] --realfloat_pp :: RealFloat a => Int -> a -> String -- | Type specialised realfloat_pp. float_pp :: Int -> Float -> String -- | Type specialised realfloat_pp. -- --
-- double_pp 4 0 --double_pp :: Int -> Double -> String -- | Read binary integer. -- --
-- unwords (map (show_bin Nothing) [0 .. 7]) == "0 1 10 11 100 101 110 111" -- unwords (map (show_bin (Just 3)) [0 .. 7]) == "000 001 010 011 100 101 110 111" --show_bin :: (Integral i, Show i) => Maybe Int -> i -> String -- | String functions. module Music.Theory.String -- | Case-insensitive ==. -- --
-- map (str_eq_ci "ci") (words "CI ci Ci cI") --str_eq_ci :: String -> String -> Bool -- | Remove r. filter_cr :: String -> String -- | Delete trailing Char where isSpace holds. -- --
-- delete_trailing_whitespace " str " == " str" -- delete_trailing_whitespace "\t\n \t\n" == "" --delete_trailing_whitespace :: String -> String -- | Variant of unwords that does not write spaces for NIL elements. -- --
-- unwords_nil [] == "" -- unwords_nil ["a"] == "a" -- unwords_nil ["a",""] == "a" -- unwords_nil ["a","b"] == "a b" -- unwords_nil ["a","","b"] == "a b" -- unwords_nil ["a","","","b"] == "a b" -- unwords_nil ["a","b",""] == "a b" -- unwords_nil ["a","b","",""] == "a b" -- unwords_nil ["","a","b"] == "a b" -- unwords_nil ["","","a","b"] == "a b" --unwords_nil :: [String] -> String -- | Variant of unlines that does not write empty lines for NIL -- elements. unlines_nil :: [String] -> String -- | unlines without a trailing newline. -- --
-- unlines (words "a b c") == "a\nb\nc\n" -- unlinesNoTrailingNewline (words "a b c") == "a\nb\nc" --unlinesNoTrailingNewline :: [String] -> String -- | Capitalise first character of word. -- --
-- capitalise "freqShift" == "FreqShift" --capitalise :: String -> String -- | Downcase first character of word. -- --
-- unCapitalise "FreqShift" == "freqShift" --unCapitalise :: String -> String -- | Apply function at each line of string. -- --
-- on_lines reverse "ab\ncde\nfg" == "ba\nedc\ngf\n" --on_lines :: (String -> String) -> String -> String -- | Regular array data as plain text tables. module Music.Theory.Array.Text -- | Tabular text. type Text_Table = [[String]] -- | Split table at indicated places. -- --
-- let tbl = [["1","2","3","4"],["A","B","E","F"],["C","D","G","H"]] -- table_split [2,2] tbl --table_split :: [Int] -> Text_Table -> [Text_Table] -- | Join tables left to right. -- --
-- table_concat [[["1","2"],["A","B"],["C","D"]],[["3","4"],["E","F"],["G","H"]]] --table_concat :: [Text_Table] -> Text_Table -- | Add a row number column at the front of the table. -- --
-- table_number_rows 0 tbl --table_number_rows :: Int -> Text_Table -> Text_Table -- | (HEADER,PAD-LEFT,EQ-WIDTH,COL-SEP,TBL-DELIM). -- -- Options are: has header pad text with space to left instead of right, -- make all columns equal width, column separator string, print table -- delimiters type Text_Table_Opt = (Bool, Bool, Bool, String, Bool) -- | Options for plain layout. table_opt_plain :: Text_Table_Opt -- | Options for simple layout. table_opt_simple :: Text_Table_Opt -- | Options for pipe layout. table_opt_pipe :: Text_Table_Opt -- | Pretty-print table. Table is in row order. -- --
-- let tbl = [["1","2","3","4"],["a","bc","def"],["ghij","klm","no","p"]] -- putStrLn$unlines$"": table_pp (True,True,True," ",True) tbl -- putStrLn$unlines$"": table_pp (False,False,True," ",False) tbl --table_pp :: Text_Table_Opt -> Text_Table -> [String] -- | Variant relying on Show instances. -- --
-- table_pp_show table_opt_simple [[1..4],[5..8],[9..12]] --table_pp_show :: Show t => Text_Table_Opt -> Table t -> [String] -- | Variant in column order (ie. transpose). -- --
-- table_pp_column_order table_opt_simple [["a","bc","def"],["ghij","klm","no"]] --table_pp_column_order :: Text_Table_Opt -> Text_Table -> [String] -- | Matrix form, ie. header in both first row and first column, in each -- case displaced by one location which is empty. -- --
-- let h = (map return "abc",map return "efgh") -- let t = table_matrix h (map (map show) [[1,2,3,4],[2,3,4,1],[3,4,1,2]]) ---- --
-- >>> putStrLn $ unlines $ table_pp table_opt_simple t -- - - - - - -- e f g h -- a 1 2 3 4 -- b 2 3 4 1 -- c 3 4 1 2 -- - - - - - --table_matrix :: ([String], [String]) -> Text_Table -> Text_Table -- | Variant that takes a show function and a header -- decoration function. -- --
-- table_matrix_opt show id ([1,2,3],[4,5,6]) [[7,8,9],[10,11,12],[13,14,15]] --table_matrix_opt :: (a -> String) -> (String -> String) -> ([a], [a]) -> Table a -> Text_Table -- | Ordinary timing durations, in H:M:S:m -- (Hours:Minutes:Seconds:milliseconds) module Music.Theory.Time.Duration -- | Duration stored as hours, minutes, seconds and -- milliseconds. data Duration Duration :: Int -> Int -> Int -> Int -> Duration [hours] :: Duration -> Int [minutes] :: Duration -> Int [seconds] :: Duration -> Int [milliseconds] :: Duration -> Int -- | Convert fractional seconds to integral -- (seconds,milliseconds). -- --
-- s_sms 1.75 == (1,750) --s_sms :: (RealFrac n, Integral i) => n -> (i, i) -- | Inverse of s_sms. -- --
-- sms_s (1,750) == 1.75 --sms_s :: Integral i => (i, i) -> Double -- | Read function for Duration tuple. The notation writes -- seconds fractionally, and allows hours and minutes to be elided if -- zero. read_duration_tuple :: String -> (Int, Int, Int, Int) -- | Read function for Duration. Allows either -- H:M:S.MS or M:S.MS or S.MS. -- --
-- read_duration "01:35:05.250" == Duration 1 35 5 250 -- read_duration "35:05.250" == Duration 0 35 5 250 -- read_duration "05.250" == Duration 0 0 5 250 --read_duration :: String -> Duration -- | Show function for Duration. Inverse of read_duration. -- Hours and minutes are always shown, even if zero. -- --
-- show_duration (Duration 1 35 5 250) == "01:35:05.250" -- show (Duration 1 15 0 000) == "01:15:00.000" -- show (Duration 0 0 3 500) == "00:00:03.500" --show_duration :: Duration -> String -- | If minutes is not in (0,59) then edit hours. normalise_minutes :: Duration -> Duration -- | If seconds is not in (0,59) then edit minutes. normalise_seconds :: Duration -> Duration -- | If milliseconds is not in (0,999) then edit seconds. normalise_milliseconds :: Duration -> Duration -- | Normalise duration so that all parts are in normal ranges. normalise_duration :: Duration -> Duration -- | Extract Duration tuple applying filter function at each element -- --
-- duration_to_tuple id (Duration 1 35 5 250) == (1,35,5,250) --duration_to_tuple :: (Int -> a) -> Duration -> (a, a, a, a) -- | Inverse of duration_to_tuple. tuple_to_duration :: (a -> Int) -> (a, a, a, a) -> Duration -- | Duration as fractional hours. -- --
-- duration_to_hours (read "01:35:05.250") == 1.5847916666666668 --duration_to_hours :: Fractional n => Duration -> n -- | Duration as fractional minutes. -- --
-- duration_to_minutes (read "01:35:05.250") == 95.0875 --duration_to_minutes :: Fractional n => Duration -> n -- | Duration as fractional seconds. -- --
-- duration_to_seconds (read "01:35:05.250") == 5705.25 --duration_to_seconds :: Fractional n => Duration -> n -- | Inverse of duration_to_hours. -- --
-- hours_to_duration 1.5847916 == Duration 1 35 5 250 --hours_to_duration :: RealFrac a => a -> Duration -- | Inverse of duration_to_minutes. minutes_to_duration :: RealFrac a => a -> Duration -- | Inverse of duration_to_seconds. seconds_to_duration :: RealFrac a => a -> Duration -- | Empty (zero) duration. nil_duration :: Duration -- | Negate the leftmost non-zero element of Duration. negate_duration :: Duration -> Duration -- | Difference between two durations as a duration. Implemented by -- translation to and from Rational fractional hours. -- --
-- duration_diff (Duration 1 35 5 250) (Duration 0 25 1 125) == Duration 1 10 4 125 -- duration_diff (Duration 0 25 1 125) (Duration 1 35 5 250) == Duration (-1) 10 4 125 -- duration_diff (Duration 0 25 1 125) (Duration 0 25 1 250) == Duration 0 0 0 (-125) --duration_diff :: Duration -> Duration -> Duration instance GHC.Classes.Eq Music.Theory.Time.Duration.Duration instance GHC.Read.Read Music.Theory.Time.Duration.Duration instance GHC.Show.Show Music.Theory.Time.Duration.Duration -- | Ordinary time and duration notations. In terms of Weeks, Days, Hours, -- Minutes, Second and Centiseconds. c.f. -- Music.Theory.Time.Duration. module Music.Theory.Time.Notation -- | Week, one-indexed, ie. 1-52 type Week = Int -- | Week, one-indexed, ie. 1-31 type Day = Int -- | Hour, zero-indexed, ie. 0-23 type Hour = Int -- | Minute, zero-indexed, ie. 0-59 type Min = Int -- | Second, zero-indexed, ie. 0-59 type Sec = Int -- | Centi-seconds, zero-indexed, ie. 0-99 type Csec = Int -- | Minutes, seconds as (min,sec) type MinSec = (Min, Sec) -- | Generic MinSec type GMinSec n = (n, n) -- | Minutes, seconds, centi-seconds as (min,sec,csec) type MinCsec = (Min, Sec, Csec) -- | Generic MinCsec type GMinCsec n = (n, n, n) -- | (Hours,Minutes,Seconds) type Hms = (Hour, Min, Sec) -- | (Days,Hours,Minutes,Seconds) type Dhms = (Day, Hour, Min, Sec) -- | Fractional days. type FDay = Double -- | Fractional hour, ie. 1.50 is one and a half hours, ie. 1 hour and 30 -- minutes. type FHour = Double -- | Fractional minute, ie. 1.50 is one and a half minutes, ie. 1 minute -- and 30 seconds, cf. FMinSec type FMin = Double -- | Fractional seconds. type FSec = Double -- | Fractional minutes and seconds (mm.ss, ie. 01.45 is 1 minute and 45 -- seconds). type FMinSec = Double -- | parseTimeOrError with defaultTimeLocale. parse_time_str :: ParseTime t => String -> String -> t format_time_str :: FormatTime t => String -> t -> String -- | Parse date in ISO-8601 extended (YYYY-MM-DD) or basic -- (YYYYMMDD) form. -- --
-- Time.toGregorian (Time.utctDay (parse_iso8601_date "2011-10-09")) == (2011,10,09) -- Time.toGregorian (Time.utctDay (parse_iso8601_date "20190803")) == (2019,08,03) --parse_iso8601_date :: String -> UTCTime -- | Format date in ISO-8601 form. -- --
-- format_iso8601_date True (parse_iso8601_date "2011-10-09") == "2011-10-09" -- format_iso8601_date False (parse_iso8601_date "20190803") == "20190803" --format_iso8601_date :: FormatTime t => Bool -> t -> String -- | Format date in ISO-8601 (YYYY-WWW) form. -- --
-- r = ["2016-W52","2011-W40"] -- map (format_iso8601_week . parse_iso8601_date) ["2017-01-01","2011-10-09"] == r --format_iso8601_week :: FormatTime t => t -> String -- | Parse ISO-8601 time is extended (HH:MM:SS) or basic -- (HHMMSS) form. -- --
-- format_iso8601_time True (parse_iso8601_time "21:44:00") == "21:44:00" -- format_iso8601_time False (parse_iso8601_time "172511") == "172511" --parse_iso8601_time :: String -> UTCTime -- | Format time in ISO-8601 form. -- --
-- format_iso8601_time True (parse_iso8601_date_time "2011-10-09T21:44:00") == "21:44:00" -- format_iso8601_time False (parse_iso8601_date_time "20190803T172511") == "172511" --format_iso8601_time :: FormatTime t => Bool -> t -> String -- | Parse date and time in extended or basic forms. -- --
-- Time.utctDayTime (parse_iso8601_date_time "2011-10-09T21:44:00") == Time.secondsToDiffTime 78240 -- Time.utctDayTime (parse_iso8601_date_time "20190803T172511") == Time.secondsToDiffTime 62711 --parse_iso8601_date_time :: String -> UTCTime -- | Format date in YYYY-MM-DD and time in HH:MM:SS -- forms. -- --
-- t = parse_iso8601_date_time "2011-10-09T21:44:00" -- format_iso8601_date_time True t == "2011-10-09T21:44:00" -- format_iso8601_date_time False t == "20111009T214400" --format_iso8601_date_time :: FormatTime t => Bool -> t -> String -- | fsec_to_minsec . * 60 -- --
-- fmin_to_minsec 6.48 == (6,29) --fmin_to_minsec :: FMin -> MinSec -- | Translate fractional seconds to picoseconds. -- --
-- fsec_to_picoseconds 78240.05 --fsec_to_picoseconds :: FSec -> Integer fsec_to_difftime :: FSec -> DiffTime -- | Translate fractional minutes.seconds to picoseconds. -- --
-- map fminsec_to_fsec [0.45,15.355] == [45,935.5] --fminsec_to_fsec :: FMinSec -> FSec fminsec_to_sec_generic :: (RealFrac f, Integral i) => f -> i -- | Fractional minutes are mm.ss, so that 15.35 is 15 minutes and 35 -- seconds. -- --
-- map fminsec_to_sec [0.45,15.35] == [45,935] --fminsec_to_sec :: FMinSec -> Sec fsec_to_fminsec :: FSec -> FMinSec sec_to_fminsec :: Sec -> FMinSec fminsec_add :: BinOp FMinSec fminsec_sub :: BinOp FMinSec fminsec_mul :: BinOp FMinSec -- | Type specialised fromInteger of floor. ffloor :: Double -> Double -- | Fractional hour to (hours,minutes,seconds). -- --
-- fhour_to_hms 21.75 == (21,45,0) --fhour_to_hms :: FHour -> Hms -- | Hms to fractional hours. -- --
-- hms_to_fhour (21,45,0) == 21.75 --hms_to_fhour :: Hms -> FHour -- | Fractional hour to seconds. -- --
-- fhour_to_fsec 21.75 == 78300.0 --fhour_to_fsec :: FHour -> FSec fhour_to_difftime :: FHour -> DiffTime -- | Time in fractional days. -- --
-- round (utctime_to_fday (parse_iso8601_date_time "2011-10-09T09:00:00")) == 55843 -- round (utctime_to_fday (parse_iso8601_date_time "2011-10-09T21:00:00")) == 55844 --utctime_to_fday :: UTCTime -> FDay -- | DiffTime in fractional seconds. -- --
-- difftime_to_fsec (hms_to_difftime (21,44,30)) == 78270 --difftime_to_fsec :: DiffTime -> FSec -- | DiffTime in fractional minutes. -- --
-- difftime_to_fmin (hms_to_difftime (21,44,30)) == 1304.5 --difftime_to_fmin :: DiffTime -> Double -- | DiffTime in fractional hours. -- --
-- difftime_to_fhour (hms_to_difftime (21,45,00)) == 21.75 --difftime_to_fhour :: DiffTime -> FHour hms_to_difftime :: Hms -> DiffTime hms_to_sec :: Hms -> Sec -- | Seconds to (hours,minutes,seconds). -- --
-- map sec_to_hms [60-1,60+1,60*60-1,60*60+1] == [(0,0,59),(0,1,1),(0,59,59),(1,0,1)] --sec_to_hms :: Sec -> Hms -- | Hms pretty printer. -- --
-- map (hms_pp True) [(0,1,2),(1,2,3)] == ["01:02","01:02:03"] --hms_pp :: Bool -> Hms -> String hms_parse :: String -> Hms -- | divMod by 60. -- --
-- sec_to_minsec 123 == (2,3) --sec_to_minsec :: Integral n => n -> GMinSec n -- | Inverse of sec_minsec. -- --
-- minsec_to_sec (2,3) == 123 --minsec_to_sec :: Num n => GMinSec n -> n -- | Convert p and q to seconds, apply f, and convert -- back to MinSec. minsec_binop :: Integral t => (t -> t -> t) -> GMinSec t -> GMinSec t -> GMinSec t -- | minsec_binop -, assumes q precedes p. -- --
-- minsec_sub (2,35) (1,59) == (0,36) --minsec_sub :: Integral n => GMinSec n -> GMinSec n -> GMinSec n -- | minsec_binop subtract, assumes p precedes -- q. -- --
-- minsec_diff (1,59) (2,35) == (0,36) --minsec_diff :: Integral n => GMinSec n -> GMinSec n -> GMinSec n -- | minsec_binop +. -- --
-- minsec_add (1,59) (2,35) == (4,34) --minsec_add :: Integral n => GMinSec n -> GMinSec n -> GMinSec n -- | foldl of minsec_add -- --
-- minsec_sum [(1,59),(2,35),(4,34)] == (9,08) --minsec_sum :: Integral n => [GMinSec n] -> GMinSec n -- | round fractional seconds to (min,sec). -- --
-- map fsec_to_minsec [59.49,60,60.51] == [(0,59),(1,0),(1,1)] --fsec_to_minsec :: FSec -> MinSec -- | MinSec pretty printer. -- --
-- map (minsec_pp . fsec_to_minsec) [59,61] == ["00:59","01:01"] --minsec_pp :: MinSec -> String minsec_parse :: (Num n, Read n) => String -> GMinSec n -- | Fractional seconds to (min,sec,csec), csec value is -- rounded. -- --
-- map fsec_to_mincsec [1,1.5,4/3] == [(0,1,0),(0,1,50),(0,1,33)] --fsec_to_mincsec :: FSec -> MinCsec -- | Inverse of fsec_mincsec. mincsec_to_fsec :: Real n => GMinCsec n -> FSec mincsec_to_csec :: Num n => GMinCsec n -> n -- | Centi-seconds to MinCsec. -- --
-- map csec_to_mincsec [123,12345] == [(0,1,23),(2,3,45)] --csec_to_mincsec :: Integral n => n -> GMinCsec n -- | MinCsec pretty printer, concise mode omits centiseconds when -- zero. -- --
-- map (mincsec_pp_opt True . fsec_to_mincsec) [1,60.5] == ["00:01","01:00.50"] --mincsec_pp_opt :: Bool -> MinCsec -> String -- | MinCsec pretty printer. -- --
-- let r = ["00:01.00","00:06.67","02:03.45"] -- map (mincsec_pp . fsec_to_mincsec) [1,6+2/3,123.45] == r --mincsec_pp :: MinCsec -> String mincsec_binop :: Integral t => (t -> t -> t) -> GMinCsec t -> GMinCsec t -> GMinCsec t -- | Convert seconds into (days,hours,minutes,seconds). sec_to_dhms_generic :: Integral n => n -> (n, n, n, n) -- | Type specialised sec_to_dhms_generic. -- --
-- sec_to_dhms 1475469 == (17,1,51,9) --sec_to_dhms :: Sec -> Dhms -- | Inverse of seconds_to_dhms. -- --
-- dhms_to_sec (17,1,51,9) == 1475469 --dhms_to_sec :: Num n => (n, n, n, n) -> n -- | Generic form of parse_dhms. parse_dhms_generic :: (Integral n, Read n) => String -> (n, n, n, n) -- | Parse DHms text. All parts are optional, order is not significant, -- multiple entries are allowed. -- --
-- parse_dhms "17d1h51m9s" == (17,1,51,9) -- parse_dhms "1s3d" == (3,0,0,1) -- parse_dhms "1h1h" == (0,2,0,0) --parse_dhms :: String -> Dhms -- | Week that t lies in. -- --
-- map (time_to_week . parse_iso8601_date) ["2017-01-01","2011-10-09"] == [52,40] --time_to_week :: UTCTime -> Week -- | Given printer, pretty print time span. span_pp :: (t -> String) -> (t, t) -> String -- | Traversable functions. module Music.Theory.Traversable -- | Replace elements at Traversable with result of joining with -- elements from list. -- --
-- let t = Tree.Node 0 [Tree.Node 1 [Tree.Node 2 [],Tree.Node 3 []],Tree.Node 4 []] -- putStrLn $ Tree.drawTree (fmap show t) -- let (_,u) = adopt_shape (\_ x -> x) "abcde" t -- putStrLn $ Tree.drawTree (fmap return u) --adopt_shape :: Traversable t => (a -> b -> c) -> [b] -> t a -> ([b], t c) -- | Two-level variant of adopt_shape. -- --
-- adopt_shape_2 (,) [0..4] (words "a bc d") == ([4],[[('a',0)],[('b',1),('c',2)],[('d',3)]])
--
adopt_shape_2 :: (Traversable t, Traversable u) => (a -> b -> c) -> [b] -> t (u a) -> ([b], t (u c))
-- | Adopt stream to shape of traversable and zip elements.
--
-- -- adopt_shape_2_zip_stream [1..] ["a", "list", "of", "strings"] --adopt_shape_2_zip_stream :: (Traversable t, Traversable u) => [c] -> t (u a) -> t (u (c, a)) -- | Two-level variant of zip [1..] -- --
-- list_number_2 ["number","list","two"] == [[(1,'n'),(2,'u'),(3,'m'),(4,'b'),(5,'e'),(6,'r')],[(7,'l'),(8,'i'),(9,'s'),(10,'t')],[(11,'t'),(12,'w'),(13,'o')]] --list_number_2 :: [[x]] -> [[(Int, x)]] -- | Variant of adopt_shape that considers only Just elements -- at Traversable. -- --
-- let s = "a(b(cd)ef)ghi"
-- let t = group_tree (begin_end_cmp_eq '(' ')') s
-- adopt_shape_m (,) [1..13] t
--
adopt_shape_m :: Traversable t => (a -> b -> c) -> [b] -> t (Maybe a) -> ([b], t (Maybe c))
-- | Tree functions
module Music.Theory.Tree
-- | Print forest as markdown list.
mdForest :: Forest String -> String
-- | Print tree as markdown list with indicated starting indent level.
mdTree :: Int -> Tree String -> [String]
-- | Tuple functions.
--
-- Uniform tuples have types T2, T3 etc. and functions
-- names are prefixed t2_ etc.
--
-- Heterogenous tuples (products) are prefixed p2_ etc.
module Music.Theory.Tuple
p2_from_list :: (t -> t1, t -> t2) -> [t] -> (t1, t2)
-- | Swap elements of P2
--
-- -- p2_swap (1,2) == (2,1) --p2_swap :: (s, t) -> (t, s) -- | Uniform two-tuple. type T2 a = (a, a) t2_from_list :: [t] -> T2 t t2_to_list :: T2 a -> [a] t2_swap :: T2 t -> T2 t t2_map :: (p -> q) -> T2 p -> T2 q t2_zipWith :: (p -> q -> r) -> T2 p -> T2 q -> T2 r t2_infix :: (a -> a -> b) -> T2 a -> b -- | t2_infix mappend. -- --
-- t2_join ([1,2],[3,4]) == [1,2,3,4] --t2_join :: Monoid m => T2 m -> m -- | t2_map mconcat of unzip -- --
-- t2_concat [("ab","cd"),("ef","gh")] == ("abef","cdgh")
--
t2_concat :: Monoid m => [T2 m] -> T2 m
-- | sort
--
-- -- t2_sort (2,1) == (1,2) --t2_sort :: Ord t => (t, t) -> (t, t) -- | sum t2_sum :: Num n => (n, n) -> n -- | mapM t2_mapM :: Monad m => (t -> m u) -> (t, t) -> m (u, u) -- | mapM_ t2_mapM_ :: Monad m => (t -> m u) -> (t, t) -> m () -- | Left rotation. -- --
-- p3_rotate_left (1,2,3) == (2,3,1) --p3_rotate_left :: (s, t, u) -> (t, u, s) p3_fst :: (a, b, c) -> a p3_snd :: (a, b, c) -> b p3_third :: (a, b, c) -> c type T3 a = (a, a, a) t3_from_list :: [t] -> T3 t t3_to_list :: T3 a -> [a] t3_rotate_left :: T3 t -> T3 t t3_fst :: T3 t -> t t3_snd :: T3 t -> t t3_third :: T3 t -> t t3_map :: (p -> q) -> T3 p -> T3 q t3_zipWith :: (p -> q -> r) -> T3 p -> T3 q -> T3 r t3_infix :: (a -> a -> a) -> T3 a -> a t3_join :: T3 [a] -> [a] t3_sort :: Ord t => (t, t, t) -> (t, t, t) p4_fst :: (a, b, c, d) -> a p4_snd :: (a, b, c, d) -> b p4_third :: (a, b, c, d) -> c p4_fourth :: (a, b, c, d) -> d p4_zip :: (a, b, c, d) -> (e, f, g, h) -> ((a, e), (b, f), (c, g), (d, h)) type T4 a = (a, a, a, a) t4_from_list :: [t] -> T4 t t4_to_list :: T4 t -> [t] t4_fst :: T4 t -> t t4_snd :: T4 t -> t t4_third :: T4 t -> t t4_fourth :: T4 t -> t t4_map :: (p -> q) -> T4 p -> T4 q t4_zipWith :: (p -> q -> r) -> T4 p -> T4 q -> T4 r t4_infix :: (a -> a -> a) -> T4 a -> a t4_join :: T4 [a] -> [a] p5_fst :: (a, b, c, d, e) -> a p5_snd :: (a, b, c, d, e) -> b p5_third :: (a, b, c, d, e) -> c p5_fourth :: (a, b, c, d, e) -> d p5_fifth :: (a, b, c, d, e) -> e p5_from_list :: (t -> t1, t -> t2, t -> t3, t -> t4, t -> t5) -> [t] -> (t1, t2, t3, t4, t5) p5_to_list :: (t1 -> t, t2 -> t, t3 -> t, t4 -> t, t5 -> t) -> (t1, t2, t3, t4, t5) -> [t] type T5 a = (a, a, a, a, a) t5_from_list :: [t] -> T5 t t5_to_list :: T5 t -> [t] t5_map :: (p -> q) -> T5 p -> T5 q t5_fst :: T5 t -> t t5_snd :: T5 t -> t t5_fourth :: T5 t -> t t5_fifth :: T5 t -> t t5_infix :: (a -> a -> a) -> T5 a -> a t5_join :: T5 [a] -> [a] p6_fst :: (a, b, c, d, e, f) -> a p6_snd :: (a, b, c, d, e, f) -> b p6_third :: (a, b, c, d, e, f) -> c p6_fourth :: (a, b, c, d, e, f) -> d p6_fifth :: (a, b, c, d, e, f) -> e p6_sixth :: (a, b, c, d, e, f) -> f type T6 a = (a, a, a, a, a, a) t6_from_list :: [t] -> T6 t t6_to_list :: T6 t -> [t] t6_map :: (p -> q) -> T6 p -> T6 q t6_sum :: Num t => T6 t -> t type T7 a = (a, a, a, a, a, a, a) t7_to_list :: T7 t -> [t] t7_map :: (p -> q) -> T7 p -> T7 q type T8 a = (a, a, a, a, a, a, a, a) t8_to_list :: T8 t -> [t] t8_map :: (p -> q) -> T8 p -> T8 q p8_third :: (a, b, c, d, e, f, g, h) -> c type T9 a = (a, a, a, a, a, a, a, a, a) t9_to_list :: T9 t -> [t] t9_from_list :: [t] -> T9 t t9_map :: (p -> q) -> T9 p -> T9 q type T10 a = (a, a, a, a, a, a, a, a, a, a) t10_to_list :: T10 t -> [t] t10_map :: (p -> q) -> T10 p -> T10 q type T11 a = (a, a, a, a, a, a, a, a, a, a, a) t11_to_list :: T11 t -> [t] t11_map :: (p -> q) -> T11 p -> T11 q type T12 t = (t, t, t, t, t, t, t, t, t, t, t, t) t12_to_list :: T12 t -> [t] t12_from_list :: [t] -> T12 t -- | foldr1 of t12_to_list. -- --
-- t12_foldr1 (+) (1,2,3,4,5,6,7,8,9,10,11,12) == 78 --t12_foldr1 :: (t -> t -> t) -> T12 t -> t -- | sum of t12_to_list. -- --
-- t12_sum (1,2,3,4,5,6,7,8,9,10,11,12) == 78 --t12_sum :: Num n => T12 n -> n uncurry3 :: (a -> b -> c -> z) -> (a, b, c) -> z uncurry4 :: (a -> b -> c -> d -> z) -> (a, b, c, d) -> z uncurry5 :: (a -> b -> c -> d -> e -> z) -> (a, b, c, d, e) -> z uncurry6 :: (a -> b -> c -> d -> e -> f -> z) -> (a, b, c, d, e, f) -> z uncurry7 :: (a -> b -> c -> d -> e -> f -> g -> z) -> (a, b, c, d, e, f, g) -> z uncurry8 :: (a -> b -> c -> d -> e -> f -> g -> h -> z) -> (a, b, c, d, e, f, g, h) -> z uncurry9 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> z) -> (a, b, c, d, e, f, g, h, i) -> z uncurry10 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> z) -> (a, b, c, d, e, f, g, h, i, j) -> z uncurry11 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> z) -> (a, b, c, d, e, f, g, h, i, j, k) -> z uncurry12 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l) -> z uncurry13 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m) -> z uncurry14 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -> z uncurry15 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -> z uncurry16 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) -> z uncurry17 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) -> z uncurry18 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) -> z uncurry19 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) -> z uncurry20 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> n -> o -> p -> q -> r -> s -> t -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) -> z -- | LGL = Large Graph Layout (NCOL, LGL) -- -- http://lgl.sourceforge.net/#FileFormat module Music.Theory.Graph.Lgl -- | (edge,weight) type Ncol_Ent t = ((t, t), Maybe Double) -- |
-- ncol_ent_format 4 ((0,1),Nothing) == "0 1" -- ncol_ent_format 4 ((0,1),Just 2.0) == "0 1 2.0000" --ncol_ent_format :: Show t => Int -> Ncol_Ent t -> String -- | Store Ncol of Int to .ncol file ncol_store :: Show t => Int -> FilePath -> Ncol t -> IO () -- | Type-specialised. ncol_store_int :: Int -> FilePath -> Ncol Int -> IO () -- | Ncol data must be un-directed and have no self-arcs. This function -- sorts edges (i,j) so that i <= j and deletes edges where i == j. ncol_rewrite_eset :: Ord t => [(t, t)] -> [(t, t)] -- | eset (edge-set) to Ncol (runs ncol_rewrite_eset) eset_to_ncol :: Ord t => [(t, t)] -> Ncol t -- | Inverse of eset_to_ncol, error if Ncol is -- weighted ncol_to_eset :: Ncol t -> [(t, t)] -- | ncol_store of eset_to_ncol ncol_store_eset :: (Ord t, Show t) => FilePath -> [(t, t)] -> IO () -- | Lgl is an adjaceny set with optional weights. type Lgl t = [(t, [(t, Maybe Double)])] -- | Format Lgl, k is floating point precision for optional weights. lgl_format :: Show t => Int -> Lgl t -> String -- | writeFile of lgl_format lgl_store :: Show t => Int -> FilePath -> Lgl t -> IO () -- | adj (adjaceny-set) to Lgl. adj_to_lgl :: Adj t -> Lgl t -- | Inverse of adj_to_lgl, error if Lgl is weighted lgl_to_adj :: Lgl t -> Adj t -- | lgl_store of adj_to_lgl lgl_store_adj :: Show t => FilePath -> Adj t -> IO () -- | Regular matrix array data, Csv, column & row indexing. module Music.Theory.Array.Csv -- | Quoting is required is the string has a double-quote, comma newline or -- carriage-return. csv_requires_quote :: String -> Bool -- | Quoting places double-quotes at the start and end and escapes -- double-quotes. csv_quote :: String -> String -- | Quote field if required. csv_quote_if_req :: String -> String -- | When reading a CSV file is the first row a header? type Csv_Has_Header = Bool -- | Alias for Char, allow characters other than , as -- delimiter. type Csv_Delimiter = Char -- | Alias for Bool, allow linebreaks in fields. type Csv_Allow_Linebreaks = Bool -- | When writing a CSV file should the delimiters be aligned, ie. should -- columns be padded with spaces, and if so at which side of the data? data Csv_Align_Columns Csv_No_Align :: Csv_Align_Columns Csv_Align_Left :: Csv_Align_Columns Csv_Align_Right :: Csv_Align_Columns -- | CSV options. type Csv_Opt = (Csv_Has_Header, Csv_Delimiter, Csv_Allow_Linebreaks, Csv_Align_Columns) -- | Default CSV options, no header, comma delimiter, no linebreaks, no -- alignment. def_csv_opt :: Csv_Opt -- | CSV table, ie. a Table with Maybe a header. type Csv_Table a = (Maybe [String], Table a) -- | Read Csv_Table from CSV file. csv_table_read :: Csv_Opt -> (String -> a) -> FilePath -> IO (Csv_Table a) -- | Read Table only with def_csv_opt. csv_table_read_def :: (String -> a) -> FilePath -> IO (Table a) -- | Read plain CSV Table. csv_table_read_plain :: FilePath -> IO (Table String) -- | Read and process CSV Csv_Table. csv_table_with :: Csv_Opt -> (String -> a) -> FilePath -> (Csv_Table a -> b) -> IO b -- | Align table according to Csv_Align_Columns. -- --
-- csv_table_align Csv_No_Align [["a","row","and"],["then","another","one"]] --csv_table_align :: Csv_Align_Columns -> Table String -> Table String -- | Pretty-print Csv_Table. csv_table_pp :: (a -> String) -> Csv_Opt -> Csv_Table a -> String -- | write_file_utf8 of csv_table_pp. csv_table_write :: (a -> String) -> Csv_Opt -> FilePath -> Csv_Table a -> IO () -- | Write Table only (no header) with def_csv_opt. csv_table_write_def :: (a -> String) -> FilePath -> Table a -> IO () -- | Write plain CSV Table. csv_table_write_plain :: FilePath -> Table String -> IO () -- | 0-indexed (row,column) cell lookup. table_lookup :: Table a -> (Int, Int) -> a -- | Row data. table_row :: Table a -> Row_Ref -> [a] -- | Column data. table_column :: Table a -> Column_Ref -> [a] -- | Lookup value across columns. table_column_lookup :: Eq a => Table a -> (Column_Ref, Column_Ref) -> a -> Maybe a -- | Table cell lookup. table_cell :: Table a -> Cell_Ref -> a -- | 0-indexed (row,column) cell lookup over column range. table_lookup_row_segment :: Table a -> (Int, (Int, Int)) -> [a] -- | Range of cells from row. table_row_segment :: Table a -> (Row_Ref, Column_Range) -> [a] -- | Translate Table to Array. It is assumed that the -- Table is regular, ie. all rows have an equal number of -- columns. -- --
-- let a = table_to_array [[0,1,3],[2,4,5]] -- in (bounds a,indices a,elems a) ---- --
-- > (((A,1),(C,2)) -- > ,[(A,1),(A,2),(B,1),(B,2),(C,1),(C,2)] -- > ,[0,2,1,4,3,5]) --table_to_array :: Table a -> Array Cell_Ref a -- | table_to_array of csv_table_read. csv_array_read :: Csv_Opt -> (String -> a) -> FilePath -> IO (Array Cell_Ref a) csv_field_str :: CSVField -> String csv_error_recover :: CSVError -> CSVRow csv_row_recover :: Either [CSVError] CSVRow -> CSVRow -- | Read irregular CSV file, ie. rows may have any number of -- columns, including no columns. csv_load_irregular :: (String -> a) -> FilePath -> IO [[a]] csv_write_irregular :: (a -> String) -> Csv_Opt -> FilePath -> Csv_Table a -> IO () csv_write_irregular_def :: (a -> String) -> FilePath -> Table a -> IO () type P2_Parser t1 t2 = (String -> t1, String -> t2) csv_table_read_p2 :: P2_Parser t1 t2 -> Csv_Opt -> FilePath -> IO (Maybe (String, String), [(t1, t2)]) type P5_Parser t1 t2 t3 t4 t5 = (String -> t1, String -> t2, String -> t3, String -> t4, String -> t5) type P5_Writer t1 t2 t3 t4 t5 = (t1 -> String, t2 -> String, t3 -> String, t4 -> String, t5 -> String) csv_table_read_p5 :: P5_Parser t1 t2 t3 t4 t5 -> Csv_Opt -> FilePath -> IO (Maybe [String], [(t1, t2, t3, t4, t5)]) csv_table_write_p5 :: P5_Writer t1 t2 t3 t4 t5 -> Csv_Opt -> FilePath -> (Maybe [String], [(t1, t2, t3, t4, t5)]) -> IO () csv_table_read_t9 :: (String -> t) -> Csv_Opt -> FilePath -> IO (Maybe [String], [T9 t]) -- | http://www.unicode.org/charts/PDF/U1D100.pdf -- -- These symbols are in http://www.gnu.org/software/freefont/, -- debian=ttf-freefont. module Music.Theory.Unicode -- | Unicode non breaking hypen character. -- --
-- non_breaking_hypen == '‑' --non_breaking_hypen :: Char -- | Unicode non breaking space character. -- --
-- non_breaking_space == ' ' --non_breaking_space :: Char -- | Unicode interpunct. -- --
-- middle_dot == '·' --middle_dot :: Char -- | The superscript variants of the digits 0-9 superscript_digits :: [Char] -- | Map show of Int to superscript_digits. -- --
-- unwords (map int_show_superscript [0,12,345,6789]) == "⁰ ¹² ³⁴⁵ ⁶⁷⁸⁹" --int_show_superscript :: Int -> String -- | The subscript variants of the digits 0-9 subscript_digits :: [Char] -- | The combining over line character. -- --
-- ['1',combining_overline] == "1̅" -- ['A',combining_overline] == "A̅" --combining_overline :: Char -- | Add combining_overline to each Char. -- --
-- overline "1234" == "1̅2̅3̅4̅" --overline :: String -> String -- | The combining under line character. -- --
-- ['1',combining_underline] == "1̲" --combining_underline :: Char -- | Add combining_underline to each Char. -- --
-- underline "1234" == "1̲2̲3̲4̲" --underline :: String -> String type Unicode_Index = Int type Unicode_Name = String type Unicode_Range = (Unicode_Index, Unicode_Index) type Unicode_Point = (Unicode_Index, Unicode_Name) type Unicode_Table = [Unicode_Point] -- | http://unicode.org/Public/11.0.0/ucd/UnicodeData.txt -- --
-- let fn = "/home/rohan/data/unicode.org/Public/11.0.0/ucd/UnicodeData.txt" -- tbl <- unicode_data_table_read fn -- length tbl == 32292 -- T.reverse_lookup_err "MIDDLE DOT" tbl == 0x00B7 -- putStrLn $ unwords $ map (\(n,x) -> toEnum n : x) $ filter (\(_,x) -> "EMPTY SET" `isInfixOf` x) tbl -- T.lookup_err 0x22C5 tbl == "DOT OPERATOR" --unicode_data_table_read :: FilePath -> IO Unicode_Table unicode_table_block :: (Unicode_Index, Unicode_Index) -> Unicode_Table -> Unicode_Table unicode_point_hs :: Unicode_Point -> String unicode_table_hs :: Unicode_Table -> String music_tbl :: [Unicode_Table] accidentals_rng_set :: [Unicode_Range] barlines_rng :: Unicode_Range -- | UNICODE barline symbols. -- --
-- let r = "𝄀𝄁𝄂𝄃𝄄𝄅" in map (toEnum . fst) barlines_tbl == r --barlines_tbl :: Unicode_Table -- | UNICODE accidental symbols. -- --
-- let r = "♭♮♯𝄪𝄫𝄬𝄭𝄮𝄯𝄰𝄱𝄲𝄳" in map (toEnum . fst) accidentals_tbl == r --accidentals_tbl :: Unicode_Table notes_rng :: Unicode_Range -- | UNICODE note duration symbols. -- --
-- let r = "𝅜𝅝𝅗𝅥𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅯𝅘𝅥𝅰𝅘𝅥𝅱𝅘𝅥𝅲" in map (toEnum . fst) notes_tbl == r --notes_tbl :: Unicode_Table rests_rng :: Unicode_Range -- | UNICODE rest symbols. -- --
-- let r = "𝄻𝄼𝄽𝄾𝄿𝅀𝅁𝅂" in map (toEnum . fst) rests_tbl == r --rests_tbl :: Unicode_Table -- | Augmentation dot. -- --
-- map toEnum [0x1D15E,0x1D16D,0x1D16D] == "𝅗𝅥𝅭𝅭" --augmentation_dot :: Unicode_Point clefs_rng :: Unicode_Range -- | UNICODE clef symbols. -- --
-- let r = "𝄞𝄟𝄠𝄡𝄢𝄣𝄤𝄥𝄦" in map (toEnum . fst) clefs_tbl == r --clefs_tbl :: Unicode_Table noteheads_rng :: Unicode_Range -- | UNICODE notehead symbols. -- --
-- let r = "𝅃𝅄𝅅𝅆𝅇𝅈𝅉𝅊𝅋𝅌𝅍𝅎𝅏𝅐𝅑𝅒𝅓𝅔𝅕𝅖𝅗𝅘𝅙𝅚𝅛" in map (toEnum . fst) noteheads_tbl == r --noteheads_tbl :: Unicode_Table stem :: Unicode_Point dynamics_rng :: Unicode_Range dynamics_tbl :: Unicode_Table articulations_rng :: Unicode_Range articulations_tbl :: Unicode_Table ix_set_to_tbl :: Unicode_Table -> [Unicode_Index] -> Unicode_Table -- | Unicode dot-operator. -- --
-- dot_operator == '⋅' --dot_operator :: Char -- | Math symbols outside of the math blocks. -- --
-- putStrLn (unicode_table_hs (ix_set_to_tbl tbl math_plain_ix)) --math_plain_ix :: [Unicode_Index] math_plain_tbl :: Unicode_Table type Unicode_Block = (Unicode_Range, String) unicode_blocks :: [Unicode_Block] -- | Bagua tri-grams. -- --
-- putStrLn $ unicode_table_hs (unicode_table_block (fst bagua) tbl) --bagua :: Unicode_Block -- | Table of eight tri-grams. -- -- HEAVEN,乾,Qián,☰,111 LAKE,兌,Duì,☱,110 FIRE,離,Lí,☲,101 -- THUNDER,震,Zhèn,☳,100 WIND,巽,Xùn,☴,011 WATER,坎,Kǎn,☵,010 -- MOUNTAIN,艮,Gèn,☶,001 EARTH,坤,Kūn,☷,000 bagua_tbl :: Unicode_Table -- | Yijing hexagrams in King Wen sequence. -- --
-- putStrLn $ unicode_table_hs (unicode_table_block (fst yijing) tbl) --yijing :: Unicode_Block -- | Yijing hexagrams in King Wen sequence. -- -- ䷀,乾,qián,111,111 ䷁,坤,kūn,000,000 ䷂,屯,chún,100,010 ䷃,蒙,méng,010,001 -- ䷄,需,xū,111,010 ䷅,訟,sòng,010,111 ䷆,師,shī,010,000 ䷇,比,bǐ,000,010 -- ䷈,小畜,xiǎo chù,111,011 ䷉,履,lǚ,110,111 ䷊,泰,tài,111,000 ䷋,否,pǐ,000,111 -- ䷌,同人,tóng rén,101,111 ䷍,大有,dà yǒu,111,101 ䷎,謙,qiān,001,000 -- ䷏,豫,yù,000,100 ䷐,隨,suí,100,110 ䷑,蠱,gŭ,011,001 ䷒,臨,lín,110,000 -- ䷓,觀,guān,000,011 ䷔,噬嗑,shì kè,100,101 ䷕,賁,bì,101,001 ䷖,剝,bō,000,001 -- ䷗,復,fù,100,000 ䷘,無妄,wú wàng,100,111 ䷙,大畜,dà chù,111,001 ䷚,頤,yí,100,001 -- ䷛,大過,dà guò,011,110 ䷜,坎,kǎn,010,010 ䷝,離,lí,101,101 ䷞,咸,xián,001,110 -- ䷟,恆,héng,011,100 ䷠,遯,dùn,001,111 ䷡,大壯,dà zhuàng,111,100 -- ䷢,晉,jìn,000,101 ䷣,明夷,míng yí,101,000 ䷤,家人,jiā rén,101,011 -- ䷥,睽,kuí,110,101 ䷦,蹇,jiǎn,001,010 ䷧,解,xiè,010,100 ䷨,損,sǔn,110,001 -- ䷩,益,yì,100,011 ䷪,夬,guài,111,110 ䷫,姤,gòu,011,111 ䷬,萃,cuì,000,110 -- ䷭,升,shēng,011,000 ䷮,困,kùn,010,110 ䷯,井,jǐng,011,010 ䷰,革,gé,101,110 -- ䷱,鼎,dǐng,011,101 ䷲,震,zhèn,100,100 ䷳,艮,gèn,001,001 ䷴,漸,jiàn,001,011 -- ䷵,歸妹,guī mèi,110,100 ䷶,豐,fēng,101,100 ䷷,旅,lǚ,001,101 ䷸,巽,xùn,011,011 -- ䷹,兌,duì,110,110 ䷺,渙,huàn,010,011 ䷻,節,jié,110,010 ䷼,中孚,zhōng fú,110,011 -- ䷽,小過,xiǎo guò,001,110 ䷾,既濟,jì jì,101,010 ䷿,未濟,wèi jì,010,101 yijing_tbl :: Unicode_Table