Почему `peek` с полиморфным Ptr возвращает GHC.Prim.Any при использовании с привязкой?

Используя привязки GNU Science Library низкого уровня 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

person daj    schedule 04.05.2015    source источник
comment
Обратите внимание, что gsl_rng_type здесь — просто переменная типа, поэтому p'gsl_rng_mt19937 имеет тип Ptr (Ptr a), и ваша попытка аналогична произнесению x <- (peek ...) :: IO (Ptr a).   -  person hammar    schedule 04.05.2015
comment
@hammar Я вижу, я запутался между переменной типа gsl_rng_type и типом C'gsl_rng. Я новичок в haskell и не знаком с тем, как привязки-dsl генерируют код FFI. Как мне передать значение gsl_rng_type в функцию alloc. В C это выглядит как gsl_rng *rng = gsl_rng_alloc(gsl_rng_mt19937).   -  person daj    schedule 04.05.2015
comment
Я предполагаю, что вам нужно будет указать указатель. Взгляните на функцию castPtr.   -  person hammar    schedule 04.05.2015
comment
Не могли бы вы добавить ответ?   -  person dfeuer    schedule 05.05.2015
comment
@dfeuer, к сожалению, я до сих пор не понимаю, что означает, что peek возвращает GHC.Prim.Any. Но мне удалось заставить работать привязки GSL с помощью castPtr, выполняющего (castPtr p'gsl_rng_mt19937) :: Ptr (Ptr C'gsl_rng_type). Также, к сожалению, я пришел к выводу, что bindings-gsl медленен как патока для моих нужд. Думаю, это из-за отсутствия небезопасных вызовов при генерации кода с помощью bindings-dsl.   -  person daj    schedule 05.05.2015
comment
Когда вы выполняете x <- peek (ptr :: Ptr (Ptr a)) в приглашении ghci, переменная типа a должна быть конкретизирована в какой-то конкретный тип. Это связано с тем, что нотация do x <- peek p означает peek p >>= \x -> ..., где .. — это то, что вы впоследствии вводите в ghci. Поскольку ghci не может знать будущее, ему приходится обманывать во время проверки типов.   -  person user2407038    schedule 05.05.2015


Ответы (1)


Чтобы немного расширить комментарий @ user2407038:

Когда вы выполняете x <- peek (ptr :: Ptr (Ptr a)) в приглашении GHCi, переменная типа a должна быть конкретизирована в какой-то конкретный тип. Это связано с тем, что обозначение do x <- peek p означает peek p >>= \x -> ..., где ... — это то, что вы впоследствии вводите в GHCi. Поскольку GHCi не может знать будущее, ему приходится «обмануть» во время проверки типов.

Напомним, что в peek p >>= \x -> ... правый аргумент >>=, а именно лямбда-абстракция \x -> ..., мономорфен по своему аргументу. Вот почему GHCi должен присвоить x мономорфный тип.

GHC.Prim.Any — это тип-заполнитель, который GHC использует в подобных ситуациях, когда необходимо назначить конкретный мономорфный тип чему-то, что не имеет других ограничений.

person Cactus    schedule 29.07.2016