标题可能不是最清楚的标题,但说实话,我不知道我不知道的事情:(
有这个Clock类:
class Clock c where
rate :: c → Double
data AudRate
data CtrRate
实例:
instance Clock AudRate where
rate _ = 44100
instance Clock CtrRate where
rate _ = 4410
我的功能:
burst :: Clock p => Double -> SigFun p () Double
burst m = proc () -> do
burstEnv <- envLineSeg [1,1,0,0] [(m/(rate (undefined :: p))), (1/4410), (m+1/4410) ] -< ()
noise <- noiseWhite 51 -< ()
outA -< noise * burstEnv
GHC告诉我:(率(undefined :: p))
Could not deduce (Clock p0) arising from a use of `rate'
from the context (Clock p)
bound by the type signature for
burst1 :: Clock p => Double -> SigFun p () Double
at Karplus.hs:11:11-49
The type variable `p0' is ambiguous
但是我使用的库的源代码中使用了相同的表达式。
outFileHelp :: forall a p. (AudioSample a, Clock p) =>
([Double] -> [Double]) -- ^ Post-processing function.
-> String -- ^ Filename to write to.
-> Double -- ^ Duration of the wav in seconds.
-> Signal p () a -- ^ Signal representing the sound.
-> IO ()
outFileHelp f filepath dur sf =
let sr = rate (undefined :: p)
numChannels = numChans (undefined :: a)
numSamples = truncate (dur * sr) * numChannels
dat = map (fromSample . (*0.999))
(f (toSamples dur sf)) :: [Int32]
-- multiply by 0.999 to avoid wraparound at 1.0
array = listArray (0, numSamples-1) dat
aud = Audio { sampleRate = truncate sr,
channelNumber = numChannels,
sampleData = array }
in exportFile filepath aud
是否可以在我的代码中使用此表达式并使GHC编译它?有延期吗?
答案 0 :(得分:5)
问题是默认情况下,类型变量仅限于单个签名。即当您在函数签名中使用p
时,编译器根本不会将此连接到您在定义中使用的undefined :: p
。相反,它会认为某些其他类型的undefined
也恰好被称为p
“。
幸运的是,GHC 可以将范围类型变量扩展为整个函数定义:
{-# LANGUAGE ScopedTypeVariables #-}
burst :: ∀ p . Clock p => Double -> SigFun p () Double
burst m = proc () -> do
burstEnv <- envLineSeg [1,1,0,0] [(m/(rate (undefined :: p))), (1/4410), (m+1/4410) ] -< ()
noise <- noiseWhite 51 -< ()
outA -< noise * burstEnv
请注意,∀ p
在示例代码中是强制性的(forall a p. (AudioSample a, Clock p)
),否则ScopedTypeVariables
根本不适用于此函数。