Como dijo Telastyn: Técnicamente, sí, a menos que haya alguna forma en su idioma para garantizar que la función de entrada también sea pura.
Eso no es hipotético, de hecho, hay buenas maneras de garantizar esto. Al menos en un lenguaje fuertemente tipado.
Una función ~ tan pura que escribirías en JavaScript como
function foo(f) {
return f(1) + 2;
}
se puede traducir directamente a Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Ahora, en JavaScript puedes hacer cosas malas como
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
Esto no es posible en Haskell . La razón es que algo como efectos secundarios console.log()
siempre debe tener un tipo de resultado IO something
, no something
solo.
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 que esta expresión escriba typecheck, necesitaríamos dar foo
la firma de tipo
foo :: (Int -> IO Int) -> Int
Pero resulta que ya no puedo implementarlo más: porque la función de argumento tiene IO
su resultado, no puedo usarlo 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
La única forma en que podría usar una IO
acción foo
es si el resultado de foo
tiene el tipo en IO Int
sí mismo:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Pero en este punto, queda claro por la firma de foo
que tampoco es una función pura.
foo = function(function bar){ print(bar.toString()) }