Come ha detto Telastyn: tecnicamente sì, a meno che non ci sia un modo nella tua lingua per garantire che anche la funzione di input sia pura.
Non è ipotetico, ci sono davvero buoni modi per garantirlo. Almeno in una lingua fortemente tipizzata.
Una funzione così pura che scriveresti in JavaScript come
function foo(f) {
return f(1) + 2;
}
può essere tradotto direttamente in Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Ora, in JavaScript puoi fare cose cattive come
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
Questo non è possibile in Haskell . Il motivo è che qualcosa di simile agli effetti collaterali console.log()
deve sempre avere un tipo di risultato IO something
, non 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)
Affinché l'espressione sia corretta, dovremmo fornire foo
la firma del tipo
foo :: (Int -> IO Int) -> Int
Ma poi non riesco più ad implementarlo: poiché la funzione argomento ha IO
come risultato, non posso usarlo all'interno 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
L'unico modo in cui potrei usare IO
un'azione foo
è se il risultato di foo
ha il tipo IO Int
stesso:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Ma a questo punto dalla firma emerge chiaramente foo
che non è nemmeno una funzione pura.
foo = function(function bar){ print(bar.toString()) }