Para sua informação: segundo dia em Haskell
MRE (o que a função faz, não importa):
foo :: Int -> Int -> Int
foo x y
| x == y = x + y
| x < y = x
| x > y = y
Isto é o que reuni sobre o ->
operador (?) até agora:
- É associativo à direita
- É usado na declaração do tipo de função para denotar o tipo de parâmetros de função, bem como seu tipo de retorno
Agora dê uma olhada na seguinte declaração de tipo de função:
foo :: Int -> Int
Isto declara (qual é a palavra apropriada?) uma função chamada foo
que recebe an Int
e retorna an Int
.
Porém, a declaração: foo :: Int -> Int -> Int
declares(?) que foo
leva 2 Int
s e retorna an Int
quando é o mesmo que dizer foo :: Int -> (Int -> Int)
which é uma função que recebe an Int
e retorna uma função que recebe an Int
e retorna an Int
.
Como isso faz sentido? Não deveria ser algo parecido com Int,Int -> Int
?
PS: O livro que estou usando: Pensando Funcionalmente com Haskell, de Richard Bird.
Nenhuma função leva dois parâmetros. Todas as funções recebem um parâmetro. Na verdade, podemos escrever:
Então o que você fez
foo 2
? Ele construiu uma nova função, uma função que receberá anInt
e retornará anInt
. É essencialmente uma versão "especializada" dofoo
withx = 2
.Então
foo :: Int -> Int -> Int
, é como sua intuição disseInt -> (Int -> Int)
: ele pega um parâmetro, anInt
, e constrói uma função que receberá o "segundo" parâmetro.Você também pode criar uma versão "sem curry" de
foo
:Agora é necessário novamente um parâmetro: uma tupla de 2 com dois
Int
s, mas, portanto, um parâmetro.A conversão entre os dois estilos acontece regularmente se você quiser "agrupar" parâmetros ou desagrupá-los. Portanto existem [Hackage] e [Hackage] , então , e .
uncurry :: (a -> b -> c) -> (a, b) -> c
curry :: ((a, b) -> c) -> a -> b -> c
foo' = uncurry foo
foo = curry foo'