В Agda, Idris, Haskell и многих других языках квантификация по типам составляет параметрический (в отличие от специального полиморфизма , где вам разрешено сопоставлять типы). С точки зрения реализации это означает, что компилятор может стереть все типы из программы, поскольку функции никогда не могут в вычислительном отношении зависеть от аргумента типа Set
. Возможность стереть типы особенно важна для языков с зависимой типизацией, поскольку типы часто могут превращаться в огромные выражения.
С более теоретической точки зрения параметрический полиморфизм хорош, потому что он позволяет нам вывести определенные свойства функции, просто взглянув на ее тип, красноречиво описанный как "свободные теоремы" Фила Уодлера . Я мог бы попытаться дать вам суть статьи, но вы должны просто пойти и прочитать ее вместо этого.
Конечно, иногда для реализации функции требуется специальный полиморфизм, поэтому у Haskell и Idris есть классы типов (Agda имеет аналогичную функцию, называемую аргументы экземпляра , и Coq имеет канонические структуры , а также классы типов). Например, в Agda вы можете определить запись следующим образом:
record ByteLength (A : Set) : Set where
field
theByteLength : Nat
open ByteLength
byteLength : (A : Set) {{_ : ByteLength A}} -> Nat
byteLength A {{bl}} = bl .theByteLength
и затем вы можете определить функцию byteLength для различных типов, определив экземпляры:
instance
byteLengthChar : ByteLength Char
byteLengthChar .theByteLength = 1
byteLengthDouble : ByteLength Double
byteLengthDouble .theByteLength = 8
С этим кодом byteLength Char
оценивается в 1
, а byteLength Double
оценивается в 8
, в то время как это вызовет ошибку типа для любого другого типа.