как неопределенный универсальный тип представляет во время выполнения ghci - PullRequest
3 голосов
/ 06 июня 2011

Я прояснил общие функции и универсальные типы данных.

В универсальном типе:

data SB = forall x. (show x) => SB x
instance Show SB where
  show (SB x) = show x

так для любого данного типа x, если он имеет сигнатуру Show, и ему обязательно будет соответствовать функция show.

но при наборе в ghci, например

:t 1

выходы

1 :: Num a => a

если связывает 1 с именем:

let a=1
:t a

теперь a имеет истинный тип.

Вопрос:

Что такое форма 1 в системе времени выполнения (до того, как она имеет тип, она имеет только Num) , поскольку она может содержать только некоторую информацию о том, чем она может быть преобразован в.

Существуют ли какие-либо внутренние функции для «упаковки» общей «информации» в реальные вещи?

Насколько я знаю сейчас, в haskell должны быть 'общие' теги для некоторых реальных вещей, но не должно быть некоторых 'чистых общих вещей'.

Привет!

возможный результат:

reference to `1` becomes:
get_const_value_1 :: (Num a) => a
get_const_value_1 = fromIntegral (1 :: Integer)

Ответы [ 2 ]

4 голосов
/ 06 июня 2011

Как сказал Дон Стюарт, классы типов в GHC реализованы с использованием «словарей».Это означает, что класс типов Num представлен как запись функций (здесь я собираюсь пропустить ограничения Eq и Show):

class Num a where
    fromInteger :: Integer -> a
    ...

становится

data Num a = Num { fromInteger :: Integer -> a, ... }

Когда вы определяете экземпляр, создается новая запись с функциями из этого экземпляра:

instance Num Integer where
    fromInteger = id
    ...

становится

numDictForInteger = Num { fromInteger = id, ... }

Теперь, когда выиспользуйте эту функцию в полиморфном контексте, компилятор не знает, какой словарь использовать, поэтому он генерирует для него дополнительный параметр:

foo :: Num a => a
foo = 1

становится

foo :: Num a -> a
foo numDict = fromInteger numDict 1

Обратите внимание, какограничение Num a => становится параметром Num a ->.


Однако, когда вы удаляете полиморфизм, компилятор знает, какой словарь использовать статически, поэтому он продолжает и вставляет его вместо генерации параметра:

foo :: Integer
foo = 1

становится

foo :: Integer
foo = fromInteger numDictForInteger 1

В качестве сноски, поэтому существует ограничение мономорфизма.Полиморфное значение не будет CAF, так как оно требует аргумента словаря.Это может привести к значительным отличиям характеристик производительности от ожидаемых, и поэтому вы вынуждены явно заявить, что это именно то, что вам нужно.

2 голосов
/ 06 июня 2011

Общие функции, которые параметризуются через класс типов, представлены в GHC как функции, которые принимают «словарь». Это структура данных, содержащая все методы конкретного экземпляра класса типов, когда создается экземпляр для данного типа.

Таким образом, функции могут быть универсальными (или «полиморфными»), как мы говорим в Haskell, в методах класса типов.

Подробнее о представлении значений GHC во время выполнения см .:

...