Haskell/Entradas e saídas simples: diferenças entre revisões

m
<source> -> <syntaxhighlight> (phab:T237267)
m (peq. correção)
m (<source> -> <syntaxhighlight> (phab:T237267))
 
 
Vale notar que há duas formas de se escrever explicitamente o tipo da saída de <code>read</code>:
<sourcesyntaxhighlight lang="haskell">
-- O tipo de 'a' é definido a partir da expressão de dentro (a partir de 'read'):
a = (read "1" :: Float)
b :: Float
b = read "2"
</syntaxhighlight>
</source>
 
A função <code>show</code> (''show'' em inglês significa "mostrar") é exatamente o oposto de <code>read</code>: ela converte um dado para uma representação em texto. Seu tipo é:
É exatamente isso que a notação <code>do</code> faz: nos permite criar sequências de ações dentro de uma função <code>IO</code>. Veja:
 
<sourcesyntaxhighlight lang="haskell">
main :: IO ()
main = do
nome <- getLine
putStrLn ("Olá, " ++ nome ++ ". Como vai?")
</syntaxhighlight>
</source>
 
{{Nota|Poderíamos explicar a fundo a notação ''do'', mas alguns outros tópicos já devem ser de nosso conhecimento para entendermos seu funcionamento. Por hora, nos basta saber usá-la, pois ela nos permite criar programas completos, com ações externas. Não é recomendável, mas caso você quera se arriscar a entender ''do'', a explicação está contida no capítulo [[Haskell/Entendendo mônadas|Entendendo mônadas]] em diante.}}
Mesmo que sejam criadas variáveis dentro de um programa, nem sempre somos obrigados a usá-las. Além do mais, dentro de uma função <code>IO</code>, <code><-</code> pode ser usada em qualquer ação, exceto a última.
 
# Um caso em que não criamos variável e, portanto, não usamos o resultado de <code>getLine</code>, apesar deste comando ser executado mesmo assim:<sourcesyntaxhighlight lang="haskell">
main = do
putStrLn "Digite seu nome:"
getLine
putStrLn "Como vai?"
</syntaxhighlight>
</source>
# Um caso em que criamos duas variáveis, mas ambas não são usadas:<sourcesyntaxhighlight lang="haskell">
main = do
x <- putStrLn "Digite seu nome:"
nome <- getLine
putStrLn "Olá. Como vai?"
</syntaxhighlight>
</source>
# Um caso em que a última ação é uma associação usando <code><-</code> e, portanto, é inválido:<sourcesyntaxhighlight lang="haskell">
main = do
x <- putStrLn "Digite seu nome:"
nome <- getLine
y <- putStrLn ("Olá, " ++ nome ++ ". Como vai?")
</syntaxhighlight>
</source>
 
No exemplo 3, teríamos um erro do compilador:
 
Outra função de <code><-</code> é extrair o dado de tipo <code>a</code> de dentro de <code>IO a</code>. Veja a seguinte linha:
<sourcesyntaxhighlight lang="haskell">
nome <- getLine
</syntaxhighlight>
</source>
Se pudéssemos usar <tt>:t</tt> para descobrir tipo de <code>nome</code>, ele seria <code>String.</code>. Como já sabemos, <code>getLine</code> é uma função sem argumentos que retorna um dado do tipo <code>IO String</code>. Ao associar seu resultado a uma variável usando <code><-</code>, o valor do tipo <code>String</code> é extraído de dentro de <code>IO String</code>. Assim, ele pode ser usado com um <code>String</code> normal. Abra o GHCi e teste por você mesmo:
 
Vejamos um simples programa de "advinho o número":
 
<sourcesyntaxhighlight lang="haskell">
adivinhe num = do
putStrLn "Digite um número:"
putStrLn "Tente novamente!"
else putStrLn "Você acertou!"
</syntaxhighlight>
</source>
 
No caso da função <code>adivinhe</code>, temos:
Não tem simplifica seu programa eliminando variáveis. Já vimos um exemplo similar:
 
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Qual o seu nome?"
putStrLn ("Olá, " ++ getLine)
</syntaxhighlight>
</source>
 
Temos um erro de tipo, pois <code>getLine</code> retorna um dado cujo tipo é <code>IO String</code>. Devemos, portanto, usar <code><-</code> para extrair o <code>String</code>:
 
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Qual o seu nome?"
nome <- getLine
putStrLn ("Olá, " ++ nome)
</syntaxhighlight>
</source>
 
=== Atenção quanto aos tipos das associações ===
Devemos ter cuidado ao criar variáveis dentro de blocos <code>do</code>, pois <code><-</code> só funciona para extrair dados. Caso o valor já seja um dado puro, não podemos associá-lo a uma variável. O exemplo a seguir resulta num erro:
 
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Digite um número inteiro:"
texto <- getLine
numero <- (read texto :: Int)
putStrLn ("O dobro do seu número é: " ++ (show (2 * numero)))
</syntaxhighlight>
</source>
Vamos interpretar o programa:
# Extraímos o <code>String</code> de dentro de <code>IO String</code>, que é o resultado de <code>getLine</code>, usando <code><-</code>.
 
Uma possível solução seria usar <code>where</code> para definir uma função interna:
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Digite um número: "
texto <- getLine
putStrLn ("O dobro do seu número é: " ++ (show . dobrar) texto)
where dobrar x = 2 * (read x :: Int)
</syntaxhighlight>
</source>
 
Outra solução é usar <code>let</code>:
|-
||
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Digite um número: "
texto <- getLine
let dobro = 2 * (read texto :: Int)
putStrLn ("O dobro do seu número é: " ++ (show dobro))
</syntaxhighlight>
</source>
||
<sourcesyntaxhighlight lang="haskell">
main = do putStrLn "Digite um número: "
texto <- getLine
let dobro = 2 * (read texto :: Int) in
do putStrLn ("O dobro do seu número é: " ++ (show dobro))
</syntaxhighlight>
</source>
|}
As duas opção são válidas, pois dentro de um bloco <code>do</code> temos a opção de usar ou não <code>in</code>.
251

edições