├── .gitignore ├── LICENSE ├── README.md ├── Setup.hs ├── TidalGuiot.cabal └── src └── Sound └── Tidal └── Guiot ├── Boot.hs ├── Control.hs ├── Functions.hs ├── Functions.hs.orig ├── Rhythm.hs ├── Scales.hs └── Utils.hs /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | *swp 3 | *un~ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Author name here (c) 2019 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tidal-guiot 2 | 3 | TidalCycles control parameters, functions, etc. 4 | 5 | ## Contents 6 | 7 | *Functions.hs*: Functions that I use every once in a while, useful for patterning things around. 8 | 9 | *Control.hs*: Defining parameters that I need to control [my SC synths](https://github.com/mxmxyz/synthdefs). 10 | 11 | *Scales.hs*: Scales I use, mostly xenharmonic. 12 | 13 | ## Installation 14 | 15 | You can install this library with cabal! To do so, type the following commands in a terminal window: 16 | 17 | ``` 18 | git clone https://github.com/mxmxyz/tidal-guiot 19 | cd tidal-guiot 20 | cabal install 21 | ``` 22 | 23 | Then, in tidal (after restarting it in case it was already running), evaluate 24 | 25 | ``` 26 | import Sound.Tidal.Guiot.Control 27 | 28 | import Sound.Tidal.Guiot.Functions 29 | 30 | import Sound.Tidal.Guiot.Scales 31 | ``` 32 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /TidalGuiot.cabal: -------------------------------------------------------------------------------- 1 | name: tidal-guiot 2 | version: 0.1.0.0 3 | -- synopsis: 4 | -- description: 5 | homepage: https://github.com/mxmxyz/tidal-guiot/README.md 6 | license: BSD3 7 | license-file: LICENSE 8 | author: Guiot 9 | category: Web 10 | build-type: Simple 11 | extra-source-files: README.md 12 | cabal-version: >=1.10 13 | 14 | library 15 | hs-source-dirs: src 16 | exposed-modules: Sound.Tidal.Guiot.Control, Sound.Tidal.Guiot.Functions, Sound.Tidal.Guiot.Scales, Sound.Tidal.Guiot.Utils, Sound.Tidal.Guiot.Boot, Sound.Tidal.Guiot.Rhythm 17 | build-depends: base >= 4.7 && < 5, tidal 18 | default-language: Haskell2010 19 | default-extensions: OverloadedStrings 20 | 21 | source-repository head 22 | type: git 23 | location: https://github.com/mxmxyz/tidal-guiot 24 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Boot.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Boot (module B) where 2 | 3 | import Sound.Tidal.Guiot.Control as B 4 | import Sound.Tidal.Guiot.Functions as B 5 | import Sound.Tidal.Guiot.Rhythm as B 6 | import Sound.Tidal.Guiot.Scales as B 7 | import Sound.Tidal.Guiot.Utils as B 8 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Control.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Control where 2 | 3 | import Sound.Tidal.Context 4 | import Sound.Tidal.Scales 5 | import Sound.Tidal.Chords 6 | 7 | -- parameters for SuperDirt synths 8 | upbound, lobound, shaped, lopf, lopq, ringfreq, ringmod, ringenv, tuning :: Pattern Double -> ControlPattern 9 | ringfreq = pF "ringfreq" 10 | ringmod = pF "ringmod" 11 | ringenv = pF "ringenv" 12 | lopf = pF "lopf" 13 | lopq = pF "lopq" 14 | shaped = pF "shaped" 15 | upbound = pF "upbound" 16 | lobound = pF "lobound" 17 | tuning = pF "tuning" 18 | pitchenv = pF "pitchenv" 19 | pitchval = pF "pitchval" 20 | bandpf = pF "bandpf" 21 | bandpq = pF "bandpq" 22 | timescale = pF "timescale" 23 | envcurve = pF "envcurve" 24 | fmfreq = pF "fmfreq" 25 | fmamt = pF "fmamt" 26 | combdel = pF "combdel" 27 | combtime = pF "combtime" 28 | attpercent = pF "attpercent" 29 | panx = pF "panx" 30 | pany = pF "pany" 31 | noise = pF "noise" 32 | lopfstart = pF "lopfstart" 33 | lopfend = pF "lopfend" 34 | tanhdist = pF "tanh" 35 | 36 | -- for "\balloon" SynthDef 37 | notea, noteb, notec, noted, envab, envbc, envcd, bandpfa, bandpfb, bandpfc, bandpqa, bandpqb, bandpqc :: Pattern Double -> ControlPattern 38 | notea = pF "notea" 39 | noteb = pF "noteb" 40 | notec = pF "notec" 41 | noted = pF "noted" 42 | envab = pF "envab" 43 | envbc = pF "envbc" 44 | envcd = pF "envcd" 45 | bandpfa = pF "bandpfa" 46 | bandpfb = pF "bandpfb" 47 | bandpfc = pF "bandpfc" 48 | bandpqa = pF "bandpqa" 49 | bandpqb = pF "bandpqb" 50 | bandpqc = pF "bandpqc" 51 | bandpga = pF "bandpga" 52 | bandpgb = pF "bandpgb" 53 | bandpgc = pF "bandpgc" 54 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Functions.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Functions where 2 | 3 | import Sound.Tidal.Context 4 | import Sound.Tidal.Scales 5 | import Sound.Tidal.Chords 6 | import Sound.Tidal.Utils 7 | 8 | import Sound.Tidal.Guiot.Utils 9 | 10 | --wrap, courtesy of @yaxu 11 | wrap s e p = (p |% (e - s)) |+ s 12 | 13 | 14 | -- | aliases for pattern rotation 15 | rotl n p = (n <~) $ p 16 | rotr n p = (n ~>) $ p 17 | shiftl = rotl 18 | shiftr = rotr 19 | 20 | -- | shifted rand 21 | shrand n = (shiftl (32.1 * n) $ rand) 22 | 23 | -- | shorthands for degradeBy 24 | degBy = degradeBy 25 | deg0 = degBy 0.0 26 | deg1 = degBy 0.1 27 | deg2 = degBy 0.2 28 | deg3 = degBy 0.3 29 | deg4 = degBy 0.4 30 | deg5 = degBy 0.5 31 | deg6 = degBy 0.6 32 | deg7 = degBy 0.7 33 | deg8 = degBy 0.8 34 | deg9 = degBy 0.9 35 | mute = degBy 1 36 | 37 | -- | shorthand for sometimesBy 38 | sBy = sometimesBy 39 | sby = sometimesBy 40 | 41 | -- | panr 42 | panr n = pan (shrand n) 43 | 44 | -- | transposing a pattern up and down 45 | transup n p = (|+ note n) $ p 46 | transdown n p = (|- note n) $ p 47 | jtransup n p = (|* note n) $ p 48 | jtransdown n p = (|* note (1/n)) $ p 49 | 50 | -- | limiter to prevent filters from going over Nyquist 51 | safety p = (min 22000) <$> p 52 | 53 | -- | palindrome of a list, with an added element in the middle 54 | paliWith :: a -> [a] -> [a] 55 | paliWith n l = l ++ [n] ++ reverse l 56 | 57 | -- | takes a list of integers and creates a boolean pattern with 1s at the steps whose number is contained in the list 58 | makeStruct :: Foldable t => Int -> t Int -> Pattern Bool 59 | makeStruct steps = fromList . indexElem steps 60 | 61 | -- | creates copies transposed to a different pitch 62 | superLayer :: Pattern Int -> Pattern Double -> Pattern ControlMap -> Pattern ControlMap 63 | superLayer n d = (|* amp (1 / (fmap fromIntegral $ n))) . (stutWith n 0 (|+ note d)) 64 | 65 | jsuperLayer :: Pattern Int -> Pattern Double -> Pattern ControlMap -> Pattern ControlMap 66 | jsuperLayer n d = (|* amp (1 / (fmap fromIntegral $ n))) . (stutWith n 0 (|* note d)) 67 | 68 | -- | the thue-morse word up to n iterations 69 | thuemorse :: Int -> [Bool] 70 | thuemorse n = (iterate thue [True])!!n 71 | where thue l = l ++ (map not l) 72 | 73 | -- | the thue-morse pattern up to n iterations 74 | thuemorsepat :: Int -> Pattern Bool 75 | thuemorsepat n = fromList $ thuemorse n 76 | 77 | -- | the tribonacci word up to n iterations 78 | tribonacci :: Int -> [Int] 79 | tribonacci n = (iterate (trib =<<) [0])!!n 80 | where trib n 81 | | n == 0 = [0,1] 82 | | n == 1 = [0,2] 83 | | otherwise = [0] 84 | 85 | -- | the tribonacci pattern up to n iterations 86 | tribonaccipat :: Int -> Pattern Int 87 | tribonaccipat n = fromList $ tribonacci n 88 | 89 | -- kindohm's mapp function 90 | -- maps a binary pattern to values inside of the list 91 | -- e.g: 92 | -- note (mapp [50,57,62] "0*2 1*3 2*4") 93 | 94 | mapp :: [Pattern a] -> Pattern Int -> Pattern a 95 | mapp mapping p = unwrap $ fmap (mapping!!) $ p 96 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Functions.hs.orig: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Functions where 2 | 3 | import Sound.Tidal.Context 4 | import Sound.Tidal.Scales 5 | import Sound.Tidal.Chords 6 | import Sound.Tidal.Utils 7 | 8 | import Sound.Tidal.Guiot.Utils 9 | 10 | --wrap, courtesy of @yaxu 11 | wrap s e p = (p |% (e - s)) |+ s 12 | 13 | --shrand, to allow for non-syncing randomness 14 | shrand n = (fast (1.453^n) $ rand) 15 | 16 | --scaleshift, to use a scale and +/- by n degrees 17 | shiftscale scale n p = scale ((+ n) <$> p) 18 | 19 | --rot aliases 20 | rotl n p = (n <~) $ p 21 | rotr n p = (n ~>) $ p 22 | shiftl = rotl 23 | shiftr = rotr 24 | 25 | --degradeBy shorthands, courtesy @kindohm 26 | degBy = degradeBy 27 | deg0 = degBy 0.0 28 | deg1 = degBy 0.1 29 | deg2 = degBy 0.2 30 | deg3 = degBy 0.3 31 | deg4 = degBy 0.4 32 | deg5 = degBy 0.5 33 | deg6 = degBy 0.6 34 | deg7 = degBy 0.7 35 | deg8 = degBy 0.8 36 | deg9 = degBy 0.9 37 | mute = degBy 1 38 | 39 | --transup and transdown (j for JI) 40 | transup n p = (|+ note n) $ p 41 | transdown n p = (|- note n) $ p 42 | jtransup n p = (|* note n) $ p 43 | jtransdown n p = (|* note (1/n)) $ p 44 | 45 | --safe filters 46 | safety p = (min 22000) <$> p 47 | 48 | --paliWith 49 | paliWith :: a -> [a] -> [a] 50 | paliWith n l = l ++ [n] ++ reverse l 51 | 52 | makeStruct :: Foldable t => Int -> t Int -> Pattern Bool 53 | makeStruct steps = fromList . indexElem steps 54 | 55 | superLayer :: Pattern Double -> Pattern Int -> Pattern ControlMap -> Pattern ControlMap 56 | superLayer d n = (|* amp (1 / (fmap fromIntegral $ n))) . (stutWith n 0 (|+ note d)) 57 | 58 | jsuperLayer :: Pattern Double -> Pattern Int -> Pattern ControlMap -> Pattern ControlMap 59 | <<<<<<< HEAD 60 | jsuperLayer d n = (|* amp (1 / (fmap fromIntegral $ n))) . (stutWith n 0 (|* note d)) 61 | ======= 62 | superLayer d n = (|* amp (1 / (fmap fromIntegral $ n))) . (stutWith n 0 (|* note d)) 63 | >>>>>>> d3980f84403e4ee45bbdc25f70bbea90b3d4241a 64 | 65 | thuemorse :: Int -> [Bool] 66 | thuemorse n = (iterate thue [True])!!n 67 | where thue l = l ++ (map not l) 68 | 69 | thuemorsepat :: Int -> Pattern Bool 70 | thuemorsepat n = fromList $ thuemorse n 71 | 72 | tribonacci :: Int -> [Int] 73 | tribonacci n = (iterate (trib =<<) [0])!!n 74 | where trib n 75 | | n == 0 = [0,1] 76 | | n == 1 = [0,2] 77 | | otherwise = [0] 78 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Rhythm.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Rhythm where 2 | 3 | import Sound.Tidal.Context 4 | 5 | {- 6 | wip/todo 7 | -- Godfried Toussaint's "hop and jump" algorithm for generating odd rhythms 8 | 9 | hopjump :: Int -> Int -> Int -> Pattern Bool 10 | hopjump onsets pulses jump = listToPat $ innerHopjump onsets pulses jump 0 (1:(replicate (pulses - 1) 0)) 11 | 12 | 13 | innerHopjump :: Int -> Int -> Int -> [Bool] -> [Bool] 14 | innerHopjump onsets pulses jump lastAdded list 15 | | (length $ filter (== True) list) == onsets = list 16 | | list!!(lastAdded + jump) == 0 = 17 | 18 | -- Godfried Toussaint's "phantom rhythms" 19 | -- every event is moved to halfway between its position and the next event's position 20 | -- (sometimes not quite halfway) 21 | -- as the phantom function is applied repeatedly, the rhythm becomes more and more even 22 | 23 | phantom :: Pattern a -> Pattern a 24 | phantom = phantomBy (1/2) (1/2) 25 | 26 | phantomBy :: Num a => a -> a -> Pattern b -> Pattern b 27 | phantomBy up down 28 | -} 29 | 30 | -- 6 basic afro-cuban rhythms 31 | 32 | -- [4-2-4-2-4] 33 | shiko :: Pattern Bool 34 | shiko = "1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0" 35 | 36 | -- [3-3-4-2-4] 37 | son :: Pattern Bool 38 | son = "1 0 0 1 0 0 1 0 0 0 1 0 1 0 0 0" 39 | 40 | -- [3-4-3-2-4] 41 | rumba :: Pattern Bool 42 | rumba = "1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0" 43 | 44 | -- [3-3-4-1-5] 45 | soukous :: Pattern Bool 46 | soukous = "1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0" 47 | 48 | -- [3-3-4-4-2] 49 | gahu :: Pattern Bool 50 | gahu = "1 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0" 51 | 52 | -- [3-3-4-3-3] 53 | bossaNova :: Pattern Bool 54 | bossaNova = "1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0" 55 | 56 | 57 | -- 2 african ternary rhythms (12 pulses) 58 | 59 | -- [2-2-3-2-3] 60 | fumefume :: Pattern Bool 61 | fumefume = "1 0 1 0 1 0 0 1 0 1 0 0" 62 | 63 | -- [2-2-1-2-2-2-1] 64 | bembe :: Pattern Bool 65 | bembe = "1 0 1 0 1 1 0 1 0 1 0 1" 66 | 67 | 68 | -- 2 aka pygmies rhythms (24 pulses) 69 | 70 | -- [3-3-3-2-3-3-2-3-2] 71 | aka1 :: Pattern Bool 72 | aka1 = "1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0" 73 | 74 | -- [3-2-2-2-3-2-2-2-2-2] 75 | aka2 :: Pattern Bool 76 | aka2 = "1 0 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0" 77 | 78 | 79 | -- 5 hourglass/isosceles rhythms 80 | 81 | -- [2-1-2] 82 | beijing1 :: Pattern Bool 83 | beijing1 = "1 0 1 1 0" 84 | 85 | -- [3-2-3] 86 | beijing2 :: Pattern Bool 87 | beijing2 = "1 0 0 1 0 1 0 0" 88 | 89 | -- [4-2-4] 90 | dhenki :: Pattern Bool 91 | dhenki = "1 0 0 0 1 0 1 0 0 0" 92 | 93 | -- [6-4-6] 94 | vijaya :: Pattern Bool 95 | vijaya = "1 0!5 1 0 0 0 1 0!5" 96 | 97 | -- [9-2-9] 98 | mathyaSamkirna :: Pattern Bool 99 | mathyaSamkirna = "1 0!8 1 0 1 0!8" 100 | 101 | 102 | -- Olivier Messiaen's favorite indian rhythms 103 | -- (from Technique de mon langage musical) 104 | 105 | -- [1-3-2-3-3-2-1-2-3-1-3] 106 | simhavrikidita :: Pattern Bool 107 | simhavrikidita = "1 1 0 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1 0 0 1 1 0 0" 108 | 109 | -- [2-3-2-12] 110 | ragavardhana :: Pattern Bool 111 | ragavardhana = "1 0 1 0 0 1 0 1 0!11" 112 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Scales.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Scales where 2 | 3 | import Data.List 4 | import Data.Fixed 5 | 6 | import Sound.Tidal.Context 7 | import Sound.Tidal.Scales 8 | import Sound.Tidal.Chords 9 | import Sound.Tidal.Utils 10 | import Sound.Tidal.Guiot.Utils 11 | 12 | -- | toScale for JI scales 13 | 14 | jtoScale' :: (Num a) => a -> [a] -> Pattern Int -> Pattern a 15 | jtoScale' _ [] = const silence 16 | jtoScale' o s = fmap noteInScale 17 | where octave x = x `div` length s 18 | noteInScale x = (s !!! x) * (o ^ octave x) 19 | 20 | jtoScale scale = jtoScale' 2 scale 21 | 22 | 23 | jrowHalf :: (Fractional a, Ord a) => a -> Int -> [a] 24 | jrowHalf interval n = map jnorm $ scanl (*) 1 $ replicate n interval 25 | 26 | -- | creates a row 27 | jrow :: (Fractional a, Ord a) => a -> Int -> Int -> [a] 28 | jrow interval right left = sort ((tail (jrowHalf interval right)) ++ jrowHalf (1 / interval) left) 29 | 30 | {- | creates a 2-intervals matrix of rational intervals and sorts it from lowest to highest. 31 | 32 | @ 33 | jmat2 (3,2,2) (5,1,1) :: [Rational] 34 | @ 35 | -} 36 | jmat2 :: (Fractional a, Ord a) => (a, Int, Int) -> (a, Int, Int) -> [a] 37 | jmat2 (int1, r1, l1) (int2, r2, l2) = sort (removeDuplicates (map jnorm ([x * y | x <- (jrow int1 r1 l1), y <- (jrow int2 r2 l2)]))) 38 | 39 | -- | moments of symmetry 40 | mos :: Int -> Int -> Int -> [Int] 41 | mos notes interval scale = take notes $ iterate ((`mod` scale) . (+ interval)) 0 42 | 43 | 44 | ---premade scales 45 | 46 | --53EDO 47 | 48 | -- | a 'superchromatic' (21 notes) scale in 53-EDO 49 | 50 | superchromatic53 :: Num a => Pattern Int -> Pattern a 51 | superchromatic53 = toScale' 53 [0, 3, 5, 9, 12, 14, 17, 19, 20, 22, 26, 27, 31, 34, 36, 39, 43, 45, 48, 50, 51] 52 | 53 | --JI 54 | 55 | -- | 'classic' chromatic scale in 5-limit intonation 56 | 57 | chromatic5l :: (Num a, Fractional a) => Pattern Int -> Pattern a 58 | chromatic5l = jtoScale [1, (16/15), (9/8), (6/5), (5/4), (4/3), (25/18), (3/2), (8/5), (5/3), (9/5), (15/8)] 59 | 60 | -- commas 61 | 62 | commaPythagorean = 531441 / 524288 63 | commaSyntonic = 81/80 64 | commaSeptimal = 64/63 65 | commaBiyatisma = 121/120 66 | -------------------------------------------------------------------------------- /src/Sound/Tidal/Guiot/Utils.hs: -------------------------------------------------------------------------------- 1 | module Sound.Tidal.Guiot.Utils where 2 | 3 | import Sound.Tidal.Context 4 | import Sound.Tidal.Utils 5 | 6 | removeDuplicates :: (Eq a) => [a] -> [a] 7 | removeDuplicates list = remDups list [] 8 | 9 | remDups :: (Eq a) => [a] -> [a] -> [a] 10 | remDups [] _ = [] 11 | remDups (x:xs) list 12 | | (x `elem` list) = remDups xs list 13 | | otherwise = x : remDups xs (x:list) 14 | 15 | jnormalize :: (Fractional a, Ord a) => a -> a 16 | jnormalize n = jnorm n 17 | 18 | jnorm :: (Fractional a, Ord a) => a -> a 19 | jnorm n 20 | | n < 1 = jnorm (n * 2) 21 | | n > 2 = jnorm (n / 2) 22 | | otherwise = n 23 | 24 | truthInt :: Bool -> Int 25 | truthInt x 26 | | x == True = 1 27 | | x == False = 0 28 | 29 | intTruth :: Int -> Bool 30 | intTruth x 31 | | x == 0 = False 32 | | otherwise = True 33 | 34 | elemInt :: (Eq a, Foldable t) => a -> t a -> Int 35 | elemInt x y = truthInt $ elem x y 36 | 37 | indexElem :: Foldable t => Int -> t Int -> [Bool] 38 | indexElem steps list = map (`elem` list) $ enumFromTo 0 steps 39 | 40 | nTimes :: (Num n, Ord n) => n -> (a -> a) -> a -> a 41 | nTimes 1 f x = f x 42 | nTimes n f x = f (nTimes (n-1) f x) 43 | 44 | applyN = nTimes 45 | --------------------------------------------------------------------------------