Согласно языковому отчету Haskell 2010, его средство проверки типов основано на на Хиндли-Милнера. Итак, рассмотрим функцию f
этого типа,
f :: forall a. [a] -> Int
Например, это может быть функция длины. По словам Хиндли-Милнера, тип f []
проверяется на Int
. Мы можем доказать это, создав экземпляр типа от f
до [Int] -> Int
и типа от []
до [Int]
, а затем сделать вывод, что приложение ([Int] -> Int) [Int]
относится к типу Int
.
В этом доказательстве я решил создать экземпляры типов forall a. [a] -> Int
и forall a. [a]
, заменив Int
на a
. Я могу заменить вместо этого Bool
, доказательство тоже работает. Разве не странно в Хиндли-Милнера, что мы можем применить полиморфный тип к другому, не указывая, какие экземпляры мы используем?
Более конкретно, что в Haskell мешает мне использовать тип a
в реализации f
? Я мог представить, что f
- это функция, которая равна 18
для любого [Bool]
и равна обычной функции длины для всех других типов списков. В этом случае f []
будет 18
или 0
? В отчете Haskell говорится, что «ядро формально не указано», поэтому трудно сказать.
f
, которая ведет себя на[Bool]
иначе, чем на других типах списков[a]
, не может существовать (т.е. не может быть написана на Haskell) из-за параметричности. В Haskell нет возможности писатьif a==Bool then ...
и иметь неизменную подписьforall a. [a] -> Int
. - person chi   schedule 10.08.2018seq
, бесконечная рекурсия), но я напоминаю, что, предполагая строгие функции, можно получить более слабую форму параметричности. (Опять же, я не могу предоставить ссылку). Чтобы полностью нарушить параметричность, можно использоватьforall a. Typeable a => [a] -> Int
, который позволяетif a==Bool then ...
- но здесь тип меняется, поэтому он на самом деле не нарушен: у нас есть тип для параметрического полиморфизма и еще один для специального (непараметрического) полиморфизма. - person chi   schedule 11.08.2018a
в Haskell вообще не нужен. И даже в Coq вы не можете исключить(a : Type)
, поэтому нет if. В Coq вам понадобится какой-то аргумент, который нужно исключить, напримерforall (a : Type), typeable a -> list a -> int
, гдеtypeable a
определено соответствующим образом, например с индуктивным определением. - person chi   schedule 11.08.2018a
лучшее, что я нашел, этоf l = if typeOf l == typeOf ([True]) then 18 else length l
. Но затемf []
вылетает с ошибкой типа. Вы видите другой путь? - person V. Semeria   schedule 11.08.2018f []
становится неоднозначным, поскольку теперьa
имеет значение. Попробуйтеf ([] :: [Bool])
илиf ([] :: [Int])
. - person chi   schedule 11.08.2018if typeOf (undefined :: a) == typeOf (undefined :: Bool)
. Лично я часто предпочитаюeqT
, поскольку он запускает уточнение GADT, но это уже другая проблема. - person chi   schedule 11.08.2018undefined :: a
, он говорит, что знаменитыйa
неизвестен. Можете ли вы дать с ним полную реализациюf
? - person V. Semeria   schedule 11.08.2018ScopedTypeVariables
, а затемfoo :: forall a. Typeable a => [a]->Int ; foo xs = if typeOf (undefined :: a) == ...
- person chi   schedule 11.08.2018