Como Telastyn disse: Tecnicamente, sim, a menos que haja alguma maneira no seu idioma para garantir que a função de entrada também seja pura.
Isso não é hipotético, existem realmente boas maneiras de garantir isso. Pelo menos em uma linguagem fortemente tipada.
Uma função ~ tão pura que você escreveria em JavaScript como
function foo(f) {
return f(1) + 2;
}
pode ser traduzido diretamente para Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Agora, em JavaScript, você pode fazer coisas más, como
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
Isso não é possível em Haskell . A razão é que algo como efeito colateral console.log()
deve sempre ter um tipo de resultado IO something
, não apenas something
sozinho.
GHCi> foo (\x -> print "muarhar" >> return 0)
<interactive>:7:12:
Couldn't match expected type ‘Int’ with actual type ‘IO b0’
In the expression: print "muarhar" >> return 0
In the first argument of ‘foo’, namely
‘(\ x -> print "muarhar" >> return 0)’
In the expression: foo (\ x -> print "muarhar" >> return 0)
Para essa expressão digitar, precisaríamos dar foo
a assinatura de tipo
foo :: (Int -> IO Int) -> Int
Mas acontece que não posso mais implementá-lo: como a função argumento tem IO
como resultado, não posso usá-la dentro foo
.
<interactive>:8:44:
Couldn't match expected type ‘Int’ with actual type ‘IO Int’
In the first argument of ‘(+)’, namely ‘f 1’
In the expression: f 1 + 2
A única maneira pela qual eu poderia usar uma IO
ação foo
é se o resultado de foo
tiver o IO Int
próprio tipo :
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Mas, neste momento, fica claro pela assinatura foo
que também não é uma função pura.
foo = function(function bar){ print(bar.toString()) }