Haskell - Tipos e classe de tipo

Haskell é uma linguagem funcional e é rigidamente tipada, o que significa que o tipo de dados usado em todo o aplicativo será conhecido pelo compilador no momento da compilação.

Classe de tipo embutido

Em Haskell, cada afirmação é considerada uma expressão matemática e a categoria desta expressão é chamada de Type. Você pode dizer que "Tipo" é o tipo de dados da expressão usada em tempo de compilação.

Para saber mais sobre o Type, usaremos o comando ": t". De uma forma genérica,Type pode ser considerado um valor, enquanto Type Classpode ser considerado como um conjunto de tipos semelhantes. Neste capítulo, aprenderemos sobre os diferentes tipos embutidos.

Int

Inté uma classe de tipo que representa os dados de tipos inteiros. Cada número inteiro dentro do intervalo de 2147483647 a -2147483647 está sob oIntclasse de tipo. No exemplo a seguir, a funçãofType() irá se comportar de acordo com seu tipo definido.

fType :: Int -> Int -> Int 
fType x y = x*x + y*y
main = print (fType 2 4)

Aqui, definimos o tipo de função fType() Como int. A função leva doisint valores e retorna um intvalor. Se você compilar e executar este trecho de código, ele produzirá a seguinte saída -

sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts 
sh-4.3$ main
20

Inteiro

Integer pode ser considerado um superconjunto de Int. Este valor não é limitado por nenhum número, portanto, um inteiro pode ter qualquer comprimento sem qualquer limitação. Para ver a diferença básica entreInt e Integer tipos, vamos modificar o código acima da seguinte maneira -

fType :: Int -> Int -> Int 
fType x y = x*x + y*y 
main = print (fType 212124454 44545454454554545445454544545)

Se você compilar o trecho de código acima, a seguinte mensagem de erro será lançada -

main.hs:3:31: Warning:            
   Literal 44545454454554545445454544545 is out of the Int range -
   9223372036854775808..9223372036854775807 
Linking main ...

Este erro ocorreu porque nossa função fType () esperava um valor de tipo Int e estamos passando algum valor de tipo Int realmente grande. Para evitar este erro, vamos modificar o tipo "Int" para "Integer" e observar a diferença.

fType :: Integer -> Integer -> Integer 
fType x y = x*x + y*y 
main = print (fType 212124454 4454545445455454545445445454544545)

Agora, ele produzirá a seguinte saída -

sh-4.3$ main
1984297512562793395882644631364297686099210302577374055141

Flutuador

Dê uma olhada no seguinte trecho de código. Mostra como funciona o tipo Float em Haskell -

fType :: Float -> Float -> Float 
fType x y = x*x + y*y 
main = print (fType 2.5 3.8)

A função assume dois valores flutuantes como entrada e produz outro valor flutuante como saída. Quando você compila e executa este código, ele produzirá a seguinte saída -

sh-4.3$ main
20.689999

Duplo

Doubleé um número de ponto flutuante com precisão dupla no final. Dê uma olhada no seguinte exemplo -

fType :: Double -> Double -> Double 
fType x y = x*x + y*y 
main = print (fType 2.56 3.81)

Quando você executa o trecho de código acima, ele irá gerar a seguinte saída -

sh-4.3$ main 
21.0697

Bool

Boolé um tipo booleano. Pode ser verdadeiro ou falso. Execute o seguinte código para entender como o tipo Bool funciona em Haskell -

main = do  
   let x = True 
   
   if x == False 
      then putStrLn "X matches with Bool Type" 
   else putStrLn "X is not a Bool Type"

Aqui, estamos definindo uma variável "x" como um Bool e comparando-a com outro valor booleano para verificar sua originalidade. Ele produzirá a seguinte saída -

sh-4.3$ main
X is not a Bool Type

Caracteres

Char representam personagens. Qualquer coisa dentro de uma aspa simples é considerada um personagem. No código a seguir, modificamos nossofType() função para aceitar o valor Char e retornar o valor Char como saída.

fType :: Char-> Char 
fType x = 'K' 
main = do  
   let x = 'v' 
   print (fType x)

O trecho de código acima chamará fType() funcionar com um charvalor de 'v', mas retorna outro valor char, ou seja, 'K'. Aqui está o resultado -

sh-4.3$ main 
'K'

Observe que não vamos usar esses tipos explicitamente porque Haskell é inteligente o suficiente para capturar o tipo antes que ele seja declarado. Nos capítulos subsequentes deste tutorial, veremos como diferentes tipos e classes de tipo tornam Haskell uma linguagem fortemente tipada.

Classe de tipo EQ

EQclasse de tipo é uma interface que fornece a funcionalidade para testar a igualdade de uma expressão. Qualquer classe de tipo que deseja verificar a igualdade de uma expressão deve fazer parte desta classe de tipo de EQ.

Todas as classes de tipo padrão mencionadas acima fazem parte deste EQclasse. Sempre que estamos verificando qualquer igualdade usando qualquer um dos tipos mencionados acima, estamos na verdade fazendo uma chamada paraEQ classe de tipo.

No exemplo a seguir, estamos usando o EQ Digite internamente usando a operação "==" ou "/ =".

main = do 
   if 8 /= 8 
      then putStrLn "The values are Equal" 
   else putStrLn "The values are not Equal"

Isso produzirá a seguinte saída -

sh-4.3$ main 
The values are not Equal

Classe de tipo ord

Ordé outra classe de interface que nos dá a funcionalidade de ordenação. Todostypes que temos usado até agora são parte disso Ordinterface. Como a interface EQ, a interface Ord pode ser chamada usando ">", "<", "<=", "> =", "compare".

Veja abaixo o exemplo em que usamos a funcionalidade de “comparação” dessa classe de tipo.

main = print (4 <= 2)

Aqui, o compilador Haskell verificará se 4 é menor ou igual a 2. Como não é, o código produzirá a seguinte saída -

sh-4.3$ main 
False

exposição

Showtem a funcionalidade de imprimir seu argumento como uma String. Qualquer que seja seu argumento, ele sempre imprime o resultado como uma String. No exemplo a seguir, imprimiremos a lista inteira usando esta interface. "show" pode ser usado para chamar esta interface.

main = print (show [1..10])

Ele produzirá a seguinte saída no console. Aqui, as aspas duplas indicam que é um valor do tipo String.

sh-4.3$ main 
"[1,2,3,4,5,6,7,8,9,10]"

Ler

Readinterface faz a mesma coisa que Mostrar, mas não imprimirá o resultado no formato String. No código a seguir, usamos oread interface para ler um valor de string e convertê-lo em um valor Int.

main = print (readInt "12") 
readInt :: String -> Int 
readInt = read

Aqui, estamos passando uma variável String ("12") para o readIntmétodo que, por sua vez, retorna 12 (um valor Int) após a conversão. Aqui está o resultado -

sh-4.3$ main 
12

Enum

Enumé outro tipo de classe Type que ativa a funcionalidade sequencial ou ordenada em Haskell. Esta classe de tipo pode ser acessada por comandos comoSucc, Pred, Bool, Charetc.

O código a seguir mostra como encontrar o valor do sucessor de 12.

main = print (succ 12)

Ele produzirá a seguinte saída -

sh-4.3$ main
13

Limitado

Todos os tipos com limites superior e inferior vêm sob esta classe de tipo. Por exemplo,Int Os dados de tipo têm limite máximo de "9223372036854775807" e limite mínimo de "-9223372036854775808".

O código a seguir mostra como Haskell determina o limite máximo e mínimo do tipo Int.

main = do 
   print (maxBound :: Int) 
   print (minBound :: Int)

Ele produzirá a seguinte saída -

sh-4.3$ main
9223372036854775807
-9223372036854775808

Agora, tente encontrar o limite máximo e mínimo dos tipos Char, Float e Bool.

Num

Esta classe de tipo é usada para operações numéricas. Tipos como Int, Integer, Float e Double estão nesta classe de tipo. Dê uma olhada no seguinte código -

main = do 
   print(2 :: Int)  
   print(2 :: Float)

Ele produzirá a seguinte saída -

sh-4.3$ main
2
2.0

Integrante

Integralpode ser considerada como uma subclasse da classe Num Type. A classe Num Type contém todos os tipos de números, enquanto a classe do tipo Integral é usada apenas para números inteiros. Int e Integer são os tipos dessa classe de tipo.

Flutuando

Como Integral, Floating também faz parte da classe Num Type, mas contém apenas números de ponto flutuante. Conseqüentemente,Float e Double vêm sob este tipo de classe.

Classe de tipo personalizado

Como qualquer outra linguagem de programação, Haskell permite que os desenvolvedores definam tipos definidos pelo usuário. No exemplo a seguir, criaremos um tipo definido pelo usuário e o usaremos.

data Area = Circle Float Float Float  
surface :: Area -> Float   
surface (Circle _ _ r) = pi * r ^ 2   
main = print (surface $ Circle 10 20 10 )

Aqui, criamos um novo tipo chamado Area. Em seguida, estamos usando este tipo para calcular a área de um círculo. No exemplo acima, "superfície" é uma função que levaArea como entrada e produz Float como a saída.

Lembre-se de que "dados" é uma palavra-chave aqui e todos os tipos definidos pelo usuário em Haskell sempre começam com uma letra maiúscula.

Ele produzirá a seguinte saída -

sh-4.3$ main
314.15927