Установка типа дробного числа

Может ли кто-нибудь объяснить, почему это компилирует

Prelude> 1 :: Num a => a

и это не

Prelude> 1.0 :: Num a => a

Второй пример будет работать с Fractional, но Num это суперкласс Fractional, Так же, как это суперкласс Integral,

3 ответа

Решение

Если у нас есть

x :: Num a => a

пользователь x можно выбрать a как и хотел. Например

x :: Int

Что бы это оценить, если x = 1.5?

По этой причине литералу с плавающей точкой нельзя дать политип Num a => a, поскольку его значение не (в общем) подходит всем NumЭрик Типы.

Целочисленные литералы вместо этого соответствуют каждому числовому типу, поэтому они разрешены.

Отношения суперкласса между классами типов не устанавливают связи между типами. Это говорит нам только о том, что если тип t является членом класса типов C, а B является суперклассом C, то t также будет членом B.

Это не говорит о том, что каждое значение v::t может использоваться в любом типе, который также является членом B. Но вот что вы заявляете:

3.14159 :: Num a => a

Важно различать полиморфизм в ОО-языках и полиморфизм в Хаскелле. ОО-полиморфизм является ковариантным, а параметрический полиморфизм Хаскелла - ко-вариантным.

Что это значит: на языке ОО, если у вас есть

class A {...}
class B: A {...}

т.е. A это суперкласс B, тогда любое значение типа B также значение типа A, (Обратите внимание, что любое конкретное значение на самом деле не является полиморфным, но имеет конкретный тип!) Таким образом, если вы имели

class Num {...}
class Fractional: Num {...}

затем Fractional значение действительно может быть использовано как Num значение. Это примерно то, что означает ковариант: любое значение подкласса также является значением суперкласса; иерархия значений идет в том же направлении, что и иерархия типов.

В Хаскеле class они разные. Нет такой вещи как "значение типа Num ", Только значения конкретных типов a, Этот тип может быть в Num учебный класс.

В отличие от ОО языков, значение как 1 :: Num a => a является полиморфным: он может принимать любой тип, который требует среда, при условии, что тип находится в Num учебный класс. (На самом деле этот синтаксис просто сокращение для 1 :: ∀ a . Num a => a читать как "для всех типов a, вы можете иметь значение 1 типа a.) Например,

Prelude> let x = 1 :: Num a => a
Prelude> x :: Int
1
Prelude> x :: Double
1.0

Вы также можете дать x более конкретное ограничение Fractional, так как это подкласс Num, Это только ограничивает тип создаваемого полиморфного значения:

Prelude> let x = 1 :: Fractional a => a
Prelude> x :: Int

<interactive>:6:1:
    No instance for (Fractional Int) arising from a use of ‘x’
    ...
Prelude> x :: Double
1.0

так как Int не дробный тип.

Таким образом, полиморфизм Хаскелла является противоречивым: полиморфные значения, ограниченные суперклассом, могут также ограничиваться подклассом, но не наоборот. В частности, вы можете иметь

Prelude> let y = 1.0 :: Fractional a => a

(y такой же как x'), но вы не можете обобщить это y' = 1.0 :: Num a => a, Это хорошо, как заметил Инго, так как в противном случае это было бы возможно сделать

Prelude> 3.14159 :: Int
  ????
Другие вопросы по тегам