2

我刚刚开始使用 Euterpea / Haskell,我正在尝试编写一个简单的脚本来随机化音符持续时间。

我写了这个有效的:

import Euterpea
playMyNote = play $ line [c 4 qn, c 4 qn, d 4 qn, e 4 qn, a 4 qn, a 4 qn, g 4 hn]

然后我读到这个:https ://www.schoolofhaskell.com/school/starting-with-haskell/libraries-and-frameworks/randoms

这显示了一种生成随机数的方法,如下所示:

import System.Random

main = do
  g <- getStdGen
  print $ take 10 (randomRs ('a', 'z') g)

我正在尝试像下面那样组合它们,但它并不完整(z例如,我不知道该放在哪里。)

谁能建议我下一步用随机定义的数字替换代表持续时间的数字?

这是我目前所在的位置:

import Euterpea
import System.Random

playRandomly = do
    z <- newStdGen
    play $ line [c 4 qn, c 4 qn, d 4 qn, e 4 qn, a 4 qn, a 4 qn, g 4 hn]


playMyNote = play $ line [c 4 qn, c 4 qn, d 4 qn, e 4 qn, a 4 qn, a 4 qn, g 4 hn]
4

1 回答 1

3

首先(通常,不仅是 Euterpea)您要查找所需数量的类型。这可以通过检查诸如等的注释函数的类型签名来看到cd结果它们都有类型

c :: Octave -> Dur -> Music Pitch

在文档中,您可以点击指向类型的链接,您会发现它Dur实际上只是Rational. 所以你真正需要的只是生成随机有理数。您有几个选项,具体取决于想要随机性的方式:

  • 为分子和分母生成随机整数,并将它们组合成一个有理数。

    playRandomly = do
       z <- newStdGen
       let (zn, zd) = split z
           numrs = randomRs (1,5) zn
           denoms = randomRs (1,4) zd
       play $ line
         [ note 4 $ fromInteger numr / fromInteger denom
         | (note, (numr,denom)) <- zip [c, c, d, e, a, a, g]
                           $ zip numrs denums
         ]
    

    获取那些单独的随机生成器然后从中获取数字真的很尴尬,请注意,使用合适的随机单子(如random-fu )更容易。

  • 生成连续可变(浮动)的持续时间,并且只将它们伪量化为有理数。

    playRandomly = do
       z <- newStdGen
       let durations = toRational <$> (randomRs (0.1,2) z :: [Float])
       play $ line
         [ note 4 duration
         | (note, duration) <- zip [c, c, d, e, a, a, g] durations
         ]
    
  • 只需从可能的持续时间列表中随机选择。这也是您可以使用 random-fu 轻松完成的事情。

于 2018-12-27T22:52:47.380 回答