为什么填充类型的孔会导致GHC编译错误?

Mat*_*eon 1 haskell ghc

下面的代码编译得很好:

ecbEncryptRandomly :: RandomGen g => ByteString -> g -> (ByteString, g)
ecbEncryptRandomly bs gen = let key :: AES
                                (key, newGen) = random gen
                            in  (ecbEncrypt key bs, newGen)
Run Code Online (Sandbox Code Playgroud)

现在,我觉得事情很漂亮,所以我想我只是为我的整个元组提供一个类型注释let:

ecbEncryptRandomly :: RandomGen g => ByteString -> g -> (ByteString, g)
ecbEncryptRandomly bs gen = let (key, newGen) = random gen :: (AES, g)
                            in  (ecbEncrypt key bs, newGen)
Run Code Online (Sandbox Code Playgroud)

GHC不喜欢这一点,并吐出以下错误:

ECBCBCoracle.hs:32:56:
Could not deduce (g ~ g1)
from the context (RandomGen g)
  bound by the type signature for
             ecbEncryptRandomly :: RandomGen g =>
                                   ByteString -> g -> (ByteString, g)
  at ECBCBCoracle.hs:31:23-71
  ‘g’ is a rigid type variable bound by
      the type signature for
        ecbEncryptRandomly :: RandomGen g =>
                              ByteString -> g -> (ByteString, g)
      at ECBCBCoracle.hs:31:23
  ‘g1’ is a rigid type variable bound by
       an expression type signature: (AES, g1) at ECBCBCoracle.hs:32:49
Relevant bindings include
  gen :: g (bound at ECBCBCoracle.hs:32:23)
  ecbEncryptRandomly :: ByteString -> g -> (ByteString, g)
    (bound at ECBCBCoracle.hs:32:1)
In the first argument of ‘random’, namely ‘gen’
In the expression: random gen :: (AES, g)
Run Code Online (Sandbox Code Playgroud)

出于某种原因,GHC似乎想让g元组成为一种新类型?关于这一点最令人困惑的是,当我使用打字的洞时,它表明我采用g了我的类型!

换句话说,以下代码:

ecbEncryptRandomly :: RandomGen g => ByteString -> g -> (ByteString, g)
ecbEncryptRandomly bs gen = let key :: AES
                                (key, _) = random gen
                            in  (ecbEncrypt key bs, _)
Run Code Online (Sandbox Code Playgroud)

生成以下错误:

ECBCBCoracle.hs:34:53:
Found hole ‘_’ with type: g
Where: ‘g’ is a rigid type variable bound by
           the type signature for
             ecbEncryptRandomly :: RandomGen g =>
                                   ByteString -> g -> (ByteString, g)
           at ECBCBCoracle.hs:31:23
Relevant bindings include
  key :: AES (bound at ECBCBCoracle.hs:33:34)
  gen :: g (bound at ECBCBCoracle.hs:32:23)
  bs :: ByteString (bound at ECBCBCoracle.hs:32:20)
  ecbEncryptRandomly :: ByteString -> g -> (ByteString, g)
    (bound at ECBCBCoracle.hs:32:1)
In the expression: _
In the expression: (ecbEncrypt key bs, _)
In the expression:
  let
    key :: AES
    (key, _) = random gen
  in (ecbEncrypt key bs, _)
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

Axm*_*an6 5

我认为你需要ScopedTypeVariables扩展,以便g值实际上是相同的g而不是分开的.