3

使用低级 GNU 科学库绑定Bindings.Gsl.RandomNumberGeneration,我在 GHCi 中遇到了这种奇怪的类型行为,其中绑定更改返回类型从 a peekinto GHC.Prim.Any。我试图理解为什么因为我不能使用c'rng_alloc除非我保留指向rng. 例如:

λ> :t c'gsl_rng_alloc
c'gsl_rng_alloc :: Ptr C'gsl_rng_type -> IO (Ptr C'gsl_rng)
λ> :t p'gsl_rng_mt19937
p'gsl_rng_mt19937 :: Ptr (Ptr gsl_rng_type)
λ> :t peek p'gsl_rng_mt19937
peek p'gsl_rng_mt19937 :: IO (Ptr gsl_rng_type)
λ> x <- peek p'gsl_rng_mt19937
λ> :t x
x :: Ptr GHC.Prim.Any
λ> c'gsl_rng_alloc x

<interactive>:421:17:
    Couldn't match type ‘GHC.Prim.Any’ with ‘C'gsl_rng_type’
    Expected type: Ptr C'gsl_rng_type
      Actual type: Ptr GHC.Prim.Any
    In the first argument of ‘c'gsl_rng_alloc’, namely ‘x’
    In the expression: c'gsl_rng_alloc x
λ> 

尝试明确指定 peek 返回的类型也无济于事:

λ> x <- (peek p'gsl_rng_mt19937) :: IO (Ptr gsl_rng_type)
λ> :t x
x :: Ptr GHC.Prim.Any
4

1 回答 1

3

要扩展 @user2407038 的评论:

当您x <- peek (ptr :: Ptr (Ptr a))在 GHCi 提示符下执行此操作时,必须将类型变量a实例化为某个具体类型。这是因为do符号x <- peek p表示peek p >>= \x -> ......之后您在 GHCi 中输入的内容在哪里。由于 GHCi 无法知道未来,所以它必须在类型检查期间“作弊”。

回想一下,在 中peek p >>= \x -> ..., 的右侧参数>>=,即 lambda 抽象\x -> ...在其参数中是单态的。这就是为什么 GHCi 必须为x.

GHC.Prim.Any是 GHC 在这种情况下使用的占位符类型,在这种情况下,需要将具体的单态类型分配给没有其他约束的东西。

于 2016-07-29T02:53:48.597 回答