使用low-level GNU Science Library bindings Bindings.Gsl.RandomNumberGeneration
,我在GHCi中遇到这种奇怪的类型行为,其中绑定更改将类型从peek
转换为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
λ>
尝试显式指定窥视返回的类型也无济于事:
λ> x <- (peek p'gsl_rng_mt19937) :: IO (Ptr gsl_rng_type)
λ> :t x
x :: Ptr GHC.Prim.Any
最佳答案
为了扩展@ user2407038的评论:
在GHCi提示符下执行x <- peek (ptr :: Ptr (Ptr a))
时,必须将类型变量a
实例化为某些具体类型。这是因为do
表示法x <- peek p
表示peek p >>= \x -> ...
,其中...
是您随后在GHCi中键入的内容。由于GHCi无法得知未来,因此必须在类型检查期间“欺骗”。
回想一下peek p >>= \x -> ...
中>>=
的右侧参数,即lambda抽象\x -> ...
,is monomorphic in its argument。这就是GHCi必须为x
指定单态类型的原因。GHC.Prim.Any
是GHC在此类情况下使用的占位符类型,在这种情况下,需要将具体的单态类型分配给没有其他约束的对象。
关于pointers - 为什么将带有多态Ptr的`peek`与绑定(bind)一起使用时返回GHC.Prim.Any?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30036017/