标题可能不是最清楚的,但说实话,我不知道我不知道的是什么:(
有这个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编译它?有延期吗?
问题是默认情况下,类型变量仅限于单个签名.即,当您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
为mandatory(forall a p. (AudioSample a, Clock p)
),否则ScopedTypeVariables
不适用于此函数.