【发布时间】:2018-02-26 23:18:57
【问题描述】:
我是 haskell 的初学者,因此我很难调试,因为它与命令式语言非常不同。当我尝试运行这段代码时,我得到了一个无限的Int 列表,但我不知道它为什么是无限的。现在我知道代码可能很丑陋而且效率不高,但我的目标只是让它工作,而不是让它高效工作。
chaineVersSon :: String -> Int -> [Int]
chaineVersSon chaineAInterpreter battementParMinute = integriser (concat
(musicaliser (freqNotes (interpreter 9 4 1 5 chaineAInterpreter []))
battementParMinute))
integriser :: [Double] -> [Int]
integriser [] = []
integriser (note:notes) = (floor (note * 32767)):integriser notes
musicaliser :: [(Double, (Double, Double))] -> Int -> [[Double]]
musicaliser [] _ = []
musicaliser (note:notes) tempo = (creerSon note tempo 0):musicaliser notes tempo
creerSon :: (Double, (Double, Double)) -> Int -> Double -> [Double]
creerSon note tempo temps
| temps < (calcDuree note tempo temps) = (echantillonner note
temps):creerSon note tempo (temps + (1/(fromIntegral frequenceEchantillonage)))
| temps == (calcDuree note tempo temps) = (echantillonner note temps):[]
calcDuree :: (Double, (Double, Double)) -> Int -> Double -> Double
calcDuree note tempo temps = (60 * (fst(snd note)) / (fromIntegral tempo)) /
(1/(fromIntegral frequenceEchantillonage)) + temps
echantillonner :: (Double, (Double, Double)) -> Double -> Double
echantillonner note temps = ((snd (snd note)) / 10) * sin(2 * pi * (fst note) * temps)
--Fonction qui traite toutes les modifications d'état
interpreter :: Int -> Int -> Double -> Double -> String -> [((Int, Int),
(Double, Double))] -> [((Int, Int), (Double, Double))]
interpreter _ _ _ _ [] _ = []
interpreter note octave duree volume (etat:chaine) pile
| etat == '0' = interpreter note octave duree 0 chaine pile
| etat == '.' = interpreter note octave (duree*1.5) volume chaine pile
| etat == '/' = interpreter note octave (duree/2) volume chaine pile
| etat == '[' = interpreter note octave duree volume chaine (((note, octave), (duree, volume)):pile)
| etat == ']' = interpreter (fst (fst save)) (snd (fst save)) (fst (snd save)) (snd (snd save)) chaine pile
| etat >= 'a' && etat <= 'g' = interpreter (changerNote etat) octave duree volume chaine pile
| etat >= '2' && etat <= '9' = interpreter note (read [etat]) duree volume chaine pile
| etat == '&' = interpreter (fst (diminuer note octave)) (snd (diminuer note octave)) duree volume chaine pile
| etat == '&' = interpreter (fst (augmenter note octave)) (snd (augmenter note octave)) duree volume chaine pile
| etat == '!' = ((note, octave), (duree, volume)):(interpreter note octave duree volume chaine pile)
| otherwise = interpreter note octave duree volume chaine pile
where save = head pile
--Fonction pour changer la note selon l'option fournie
changerNote :: Char -> Int
changerNote etat
| etat == 'a' = 9
| etat == 'b' = 11
| etat == 'c' = 0
| etat == 'd' = 2
| etat == 'e' = 4
| etat == 'f' = 5
| etat == 'g' = 7
--Fonction qui diminue la note et l'octave si possible/nécéssaire
diminuer :: Int -> Int -> (Int, Int)
diminuer note octave
| note > 0 = (note - 1, octave)
| note == 0 && octave == 2 = (note, octave)
| otherwise = (11, octave - 1)
--Fonction qui augmente la note et l'octave si possible/nécéssaire
augmenter :: Int -> Int -> (Int, Int)
augmenter note octave
| note < 11 = (note + 1, octave)
| note == 11 && octave == 9 = (note, octave)
| otherwise = (0, octave + 1)
--Fonction récursive pour calculer la fréquence de chaque note à jouer
freqNotes :: [((Int, Int), (Double, Double))] -> [(Double, (Double, Double))]
freqNotes [] = []
freqNotes (note:notes) = ((calcFrequence (fromIntegral (fst (fst note))) (fromIntegral (snd (fst note)))), (fst (snd note), snd (snd note))):freqNotes notes
--Fonction qui calcule la fréquence selon la note et l'octave
calcFrequence :: Double -> Double -> Double
calcFrequence note octave = 440 * (2**(1/12))**((12 * octave) + note - 57)
main::IO()
main = do argv <- getArgs
chaine <- readFile ( argv !! 0 )
print "Begin..."
print ( chaineVersSon chaine ( ( read ( argv !! 1 ) ) :: Int ) )
print "Done!"
通常在其他语言中,我只会在任何地方打印内容并查看结果出错的地方,但我不知道如何在 Haskell 中做到这一点,而无需重写几乎整个代码。我应该使用什么样的方法来查找我的代码出错的地方?
我已经阅读过有关跟踪的信息,但我似乎无法用它实际打印任何内容。
【问题讨论】:
-
请将此设为minimal reproducible example。如果你不能轻易地减少它们,那么一些丑陋/不需要的行并不是一个太糟糕的问题,但是如果你的程序需要外部文件和/或命令行参数,我们几乎无法验证它。最好以 GHCi 的单个函数调用为例。
标签: haskell