Haskell — это функциональный язык, и он строго типизирован, что означает, что тип данных, используемый во всем приложении, будет известен компилятору во время компиляции.
Класс встроенного типа
В Haskell каждое утверждение рассматривается как математическое выражение, а категория этого выражения называется типом . Вы можете сказать, что «Тип» — это тип данных выражения, используемого во время компиляции.
Чтобы узнать больше о типе , мы будем использовать команду «: t». В общем случае Type можно рассматривать как значение, тогда как Type Class можно рассматривать как набор похожих типов. В этой главе мы узнаем о различных встроенных типах.
Int
Int является классом типа, представляющим данные типа Integer. Каждое целое число в диапазоне от 2147483647 до -2147483647 относится к классу типа Int . В следующем примере функция fType () будет вести себя в соответствии с определенным типом.
fType :: Int -> Int -> Int fType x y = x*x + y*y main = print (fType 2 4)
Здесь мы установили тип функции fType () как int . Функция принимает два значения типа int и возвращает одно значение типа int . Если вы скомпилируете и выполните этот фрагмент кода, он выдаст следующий вывод:
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts sh-4.3$ main 20
целое число
Целое число можно рассматривать как надмножество Int . Это значение не ограничено никаким числом, поэтому целое число может иметь любую длину без каких-либо ограничений. Чтобы увидеть основное различие между типами Int и Integer , давайте изменим приведенный выше код следующим образом:
fType :: Int -> Int -> Int fType x y = x*x + y*y main = print (fType 212124454 44545454454554545445454544545)
Если вы скомпилируете указанный выше фрагмент кода, появится следующее сообщение об ошибке:
main.hs:3:31: Warning: Literal 44545454454554545445454544545 is out of the Int range - 9223372036854775808..9223372036854775807 Linking main ...
Эта ошибка произошла из-за того, что наша функция fType () ожидала одно значение типа Int, и мы передали какое-то очень большое значение типа Int. Чтобы избежать этой ошибки, давайте изменим тип «Int» на «Integer» и наблюдаем разницу.
fType :: Integer -> Integer -> Integer fType x y = x*x + y*y main = print (fType 212124454 4454545445455454545445445454544545)
Теперь он выдаст следующий результат:
sh-4.3$ main 1984297512562793395882644631364297686099210302577374055141
терка
Посмотрите на следующий фрагмент кода. Он показывает, как работает тип Float в Haskell —
fType :: Float -> Float -> Float fType x y = x*x + y*y main = print (fType 2.5 3.8)
Функция принимает два значения с плавающей запятой в качестве входных данных и возвращает другое значение с плавающей запятой в качестве выходных данных. Когда вы скомпилируете и выполните этот код, он выдаст следующий вывод:
sh-4.3$ main 20.689999
двойной
Double — число с плавающей запятой с двойной точностью в конце. Взгляните на следующий пример —
fType :: Double -> Double -> Double fType x y = x*x + y*y main = print (fType 2.56 3.81)
Когда вы выполните приведенный выше фрагмент кода, он сгенерирует следующий вывод:
sh-4.3$ main 21.0697
Bool
Bool — это логический тип. Это может быть как True, так и False. Выполните следующий код, чтобы понять, как работает тип Bool в Haskell:
main = do let x = True if x == False then putStrLn "X matches with Bool Type" else putStrLn "X is not a Bool Type"
Здесь мы определяем переменную «x» как Bool и сравниваем ее с другим логическим значением, чтобы проверить ее оригинальность. Это даст следующий результат —
sh-4.3$ main X is not a Bool Type
голец
Чар представляет персонажей. Все, что находится в одинарной кавычке, считается символом. В следующем коде мы изменили нашу предыдущую функцию fType (), чтобы она принимала значение Char и возвращала значение Char в качестве вывода.
fType :: Char-> Char fType x = 'K' main = do let x = 'v' print (fType x)
Приведенный выше фрагмент кода вызовет функцию fType () со значением char, равным «v», но возвращает другое значение char, то есть «K». Вот его вывод —
sh-4.3$ main 'K'
Обратите внимание, что мы не собираемся использовать эти типы явно, потому что Haskell достаточно умен, чтобы перехватить тип до того, как он будет объявлен. В последующих главах этого урока мы увидим, как различные типы и классы типов делают язык Haskell строго типизированным.
Класс эквалайзера
Класс EQ type — это интерфейс, который предоставляет функциональные возможности для проверки равенства выражения. Любой класс Type, который хочет проверить равенство выражения, должен быть частью этого класса EQ Type.
Все упомянутые выше стандартные классы типа являются частью этого класса EQ . Всякий раз, когда мы проверяем какое-либо равенство, используя любой из типов, упомянутых выше, мы фактически вызываем класс EQ .
В следующем примере мы используем тип EQ для внутреннего использования операции «==» или «/ =».
main = do if 8 /= 8 then putStrLn "The values are Equal" else putStrLn "The values are not Equal"
Это даст следующий вывод —
sh-4.3$ main The values are not Equal
Тип Орд Класс
Ord — это еще один интерфейсный класс, который дает нам функциональность упорядочения. Все типы, которые мы использовали до сих пор, являются частью этого интерфейса Ord . Как и интерфейс EQ, интерфейс Ord можно вызывать с помощью «>», «<», «<=», «> =», «сравнить».
Ниже приведен пример, где мы использовали «сравнить» функциональность этого класса типов.
main = print (4 <= 2)
Здесь компилятор Haskell проверит, меньше ли 4 или равно 2. Так как это не так, код выдаст следующий вывод:
sh-4.3$ main False
Шоу
Функция Show имеет функцию печати аргумента в виде строки. Каким бы ни был его аргумент, он всегда печатает результат в виде строки. В следующем примере мы распечатаем весь список, используя этот интерфейс. «show» может использоваться для вызова этого интерфейса.
main = print (show [1..10])
Он выдаст следующий вывод на консоль. Здесь двойные кавычки указывают, что это значение типа String.
sh-4.3$ main "[1,2,3,4,5,6,7,8,9,10]"
Читать
Интерфейс Read делает то же самое, что и Show, но не выводит результат в формате String. В следующем коде мы использовали интерфейс read для чтения строкового значения и преобразования его в значение Int.
main = print (readInt "12") readInt :: String -> Int readInt = read
Здесь мы передаем переменную String («12») методу readInt, который, в свою очередь, возвращает 12 (значение Int) после преобразования. Вот его вывод —
sh-4.3$ main 12
Enum
Enum — это другой тип класса Type, который включает последовательную или упорядоченную функциональность в Haskell. Этот класс Type может быть доступен с помощью таких команд, как Succ, Pred, Bool, Char и т. Д.
Следующий код показывает, как найти значение преемника 12.
main = print (succ 12)
Это даст следующий результат —
sh-4.3$ main 13
ограниченный
Все типы, имеющие верхнюю и нижнюю границы, подпадают под этот класс типов. Например, данные типа Int имеют максимальную границу «9223372036854775807» и минимальную границу «-9223372036854775808».
Следующий код показывает, как Haskell определяет максимальную и минимальную границы типа Int.
main = do print (maxBound :: Int) print (minBound :: Int)
Это даст следующий результат —
sh-4.3$ main 9223372036854775807 -9223372036854775808
Теперь попробуйте найти максимальную и минимальную границы типов Char, Float и Bool.
Num
Этот тип класса используется для числовых операций. Такие типы, как Int, Integer, Float и Double подпадают под этот класс Type. Посмотрите на следующий код —
main = do print(2 :: Int) print(2 :: Float)
Это даст следующий результат —
sh-4.3$ main 2 2.0
интеграл
Интеграл можно рассматривать как подкласс класса Num Type. Класс Num Type содержит все типы чисел, тогда как класс Integral используется только для целых чисел. Int и Integer являются типами в этом классе типов.
плавучий
Как и Integral, Floating также является частью класса Num Type, но он содержит только числа с плавающей запятой. Следовательно, Float и Double подпадают под этот тип класса.
Класс пользовательского типа
Как и любой другой язык программирования, Haskell позволяет разработчикам определять пользовательские типы. В следующем примере мы создадим пользовательский тип и используем его.
data Area = Circle Float Float Float surface :: Area -> Float surface (Circle _ _ r) = pi * r ^ 2 main = print (surface $ Circle 10 20 10 )
Здесь мы создали новый тип с именем Area . Далее мы используем этот тип для расчета площади круга. В приведенном выше примере «поверхность» — это функция, которая принимает Площадь в качестве входных данных и создает Float в качестве выходных данных.
Имейте в виду, что «данные» — это ключевое слово, и все пользовательские типы в Haskell всегда начинаются с заглавной буквы.
Это даст следующий результат —