Quantise type

Not sure if this qualifies as an innards topic, but here goes. Studiously working through all the reference tutorials, The quantise example fails because of a type error:

d1 $ s "superchip*8" # n (quantise 1 $ range (-10) (10) $ slow 8 $ cosine) 
                     # release (quantise 5 $ slow 8 $ sine + 0.1)

Throws the error: "No instance for (RealFrac Note) arising from a use of ‘quantise’

Not good enough at haskell types yet, to decipher how to fix this.

The only other discrepancy I've found in the tutorials was the problem with '<>' which I could resolve with helpful instructions from this post: How to use the operator <> of overlay - #2 by fnab

RealFrac is the type class that holds the round method that is used in quantize. Note is currently not an instance of RealFrac. Perhaps it should be? Especially in light of the comment (Note is Double)

class (Real a, Fractional a) => RealFrac a where
  round :: Integral b => a -> b

quantise :: (Functor f, RealFrac b) => b -> f b -> f b
quantise n = fmap ((/n) . (fromIntegral :: RealFrac b => Int -> b) . round . (*n))

-- | Note is Double, but with a different parser
newtype Note = Note { unNote :: Double } 
  deriving (Typeable, Data, Generic, Eq, Ord, Enum, Num, 
    Fractional, Floating, Real)

one could just add RealFrac to the deriving clause.

To test it (without changing the library), one can do (in a ghci session)

tidal> :set -XGeneralizedNewtypeDeriving -XStandaloneDeriving 
tidal> deriving instance RealFrac Note

then the example works (I think - It does type-check and play some sound).

Thanks! This was really helpful and I think it does solve the problem, although it seems a bit odd to declare a Note to also be a 2 part construction lie a RealFrac. OTOH I spent the last hour engaged in hacking away at the Haskell type system (or as I like to call it- passive suicidal ideation) to come up with a solution attached to quantise, but came up empty handed. Currently planning to accept your fix and make some music. :-]

I think this deserves an issue

1 Like

Looks like RealFrac is a subclass of Real and Fractional which are already in the Note deriving classes, so I would think it just needs to be added to the list. But I am currently driving Haskell w/o a license...

Ah... I see Jwaldman had all this sorted in their first note. Looks right to me.