Понимание Haskell RankNTypes Сообщение об ошибке - PullRequest
3 голосов
/ 09 мая 2019

Я пытаюсь понять RankNTypes.

Почему компилятор жалуется, что в этом случае a НЕ может быть [a]?

> :{
> | tupleF2 :: (forall a . a -> b) -> (a1, a2) -> (b, b)
> | tupleF2 elemF2 (x, y) = (elemF2 x, elemF2 y)
> | :}

> :t tupleF2  tupleF2 :: (forall a. a -> b) -> (a1, a2) -> (b, b)

> :t tupleF2 length

<interactive>:1:9: error:
    • Couldn't match type ‘a’ with ‘[a0]’
      ‘a’ is a rigid type variable bound by
        a type expected by the context:
          forall a. a -> Int
        at <interactive>:1:1-14
      Expected type: a -> Int
        Actual type: [a0] -> Int
    • In the first argument of ‘tupleF2’, namely ‘length’
      In the expression: tupleF2 length

Хотя следующие проверки типов хорошо? и t в порядке с t a.

> :t tupleF length
tupleF length :: Foldable t => (t a, t a) -> (Int, Int)
:t tupleF
tupleF :: (t -> b) -> (t, t) -> (b, b)

Вышеуказанная ошибка компиляции происходит только при включении RankNTypes. Любые указатели в понимании того, что происходит, было бы замечательно.

Спасибо.

1 Ответ

5 голосов
/ 09 мая 2019

forall a . a -> b - это тип функции f, которая может преобразовать значение любого типа a в некоторое значение типа b. Обратите внимание, что f должен быть готов принимать абсолютно все в качестве входных данных, то есть все они должны проверять тип

f ()
f 32
f True
f 'a'
f "hello"
f (True, [2], False)

length не удовлетворяет этому требованию, например, length () напечатан плохо - length хочет в качестве входных данных складывать (например, список), а () не в порядке.

Следовательно, tupleF2 length плохо напечатано.

Прагматично, обратите внимание, что f может быть только постоянной функцией, как

f x = True  -- assuming b = Bool

Действительно, параметричность гарантирует, что только постоянная функция может иметь тип forall a . a -> b. Вы можете попробовать tupleF2 (const True) ((),"hello") и получить (True, True).

...