I have upgraded my codebase from GHC-8.10, to 9.2 this morning, and I am having trouble resolving an issue:
Instance head cannot contain nested ‘forall’s or contexts
In an instance declaration
|
211 | instance (SingDSI padding => Bin.Binary (BinaryBlobPadded padding typ)) where
I have some code, that deals with binary-blobs, and can automatically pad them to either 32 or 64 bytes. I was trying to learn about TypeFamilies about 6 months ago, and thought this would be a good place to try them out, by encoding the padding. However, on returning to the code, its melting my brain a bit!
The original article I took insiration & code from was:
https://blog.jle.im/entry/introduction-to-singletons-1.html
which I adapted to my own case.
data BlockPadding = BlockPaddingNone
| BlockPadding32
| BlockPadding64
deriving (Generic)
deriving anyclass (NoThunks)
deriving anyclass (NFData)
newtype BinaryBlobPadded (padding::BlockPadding) typ = BinaryBlobPadded W8.ByteString
deriving (Show,Generic)
deriving anyclass (NoThunks)
deriving anyclass (NFData)
type BinaryBlobPad32 typ = BinaryBlobPadded 'BlockPadding32 typ
type BinaryBlobPad64 typ = BinaryBlobPadded 'BlockPadding64 typ
data SBlockPadding :: BlockPadding -> Type where
SBlockPaddingNone :: SBlockPadding 'BlockPaddingNone
SBlockPadding32 :: SBlockPadding 'BlockPadding32
SBlockPadding64 :: SBlockPadding 'BlockPadding64
--Creates the following 3 values:
--SBlockPaddingNone :: SBlockPadding 'BlockPaddingNone
--SBlockPadding32 :: SBlockPadding 'BlockPadding32
--SBlockPadding64 :: SBlockPadding 'BlockPadding64
getBlockPadding :: SBlockPadding s -> (BinaryBlobPadded s typ) -> BlockPadding
getBlockPadding SBlockPaddingNone _ = BlockPaddingNone
getBlockPadding SBlockPadding32 _ = BlockPadding32
getBlockPadding SBlockPadding64 _ = BlockPadding64
class SingDSI s where
singDS :: SBlockPadding s
instance SingDSI 'BlockPaddingNone where
singDS = SBlockPaddingNone
instance SingDSI 'BlockPadding32 where
singDS = SBlockPadding32
instance SingDSI 'BlockPadding64 where
singDS = SBlockPadding64
getBlockPadding' :: SingDSI s => (BinaryBlobPadded s typ) -> BlockPadding
getBlockPadding' = getBlockPadding singDS
instance (SingDSI padding => Bin.Binary (BinaryBlobPadded padding typ)) where
get = error "TODO"
put block@(BinaryBlobPadded bytes) = do
let n = W8.length bytes
let p = calcNPadding (getBlockPadding' block) n
Bin.Put.putByteString bytes
Bin.Put.putByteString (W8.replicate p paddingValue)
paddingValue :: Word8
paddingValue = 0xEE
GHC is complaining about the instance, but I am not sure why. Is there a simple fix here, or am I going to need to do a major refactor here, to make the code compatible with GHC-9.2.
Many thanks for any insight, in advance.