问题
Using the low-level GNU Science Library bindings Bindings.Gsl.RandomNumberGeneration, I'm running into this odd type behavior in GHCi where binding changes return type from a peek
into GHC.Prim.Any
. I'm trying to understand why since I can't use the c'rng_alloc
unless I retain the type of pointer to an rng
. For eample:
λ> :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
λ>
Trying to explicitly specify the type of the peek return that doesn't help either:
λ> x <- (peek p'gsl_rng_mt19937) :: IO (Ptr gsl_rng_type)
λ> :t x
x :: Ptr GHC.Prim.Any
回答1:
To expand somewhat on @user2407038's comment:
When you do
x <- peek (ptr :: Ptr (Ptr a))
in the GHCi prompt, the type variablea
must be instantiated to some concrete type. This is because thedo
notationx <- peek p
meanspeek p >>= \x -> ...
, where...
is what you type into GHCi afterwards. Since GHCi can't know the future, it has to "cheat" during typechecking.
Recall that in peek p >>= \x -> ...
, the right-hand argument to >>=
, namely the lambda abstraction \x -> ...
, is monomorphic in its argument. This is why GHCi has to assign a monomorphic type to x
.
GHC.Prim.Any
is the placeholder type that GHC uses in situations like this where a concrete, monomorphic type needs to be assigned to something that has no other constraints.
来源:https://stackoverflow.com/questions/30036017/why-does-peek-with-a-polymorphic-ptr-return-ghc-prim-any-when-used-with-a-bind