Jak powiedział Telastyn: Technicznie tak, chyba że w twoim języku jest jakiś sposób na zagwarantowanie, że funkcja wprowadzania danych jest również czysta.
To nie jest hipotetyczne, istnieją naprawdę dobre sposoby, aby to zagwarantować. Przynajmniej w silnie napisanym języku.
Taką czystą ~ funkcję, którą napisalibyście w JavaScript jako
function foo(f) {
return f(1) + 2;
}
można przetłumaczyć bezpośrednio na Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Teraz w JavaScript możesz robić złe rzeczy, takie jak
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
W Haskell nie jest to możliwe . Powodem jest to, że coś takiego jak efekt uboczny console.log()
musi zawsze mieć typ wyniku IO something
, a nie tylko something
sam.
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)
Aby to wyrażenie mogło sprawdzić typ, musielibyśmy podać foo
podpis typu
foo :: (Int -> IO Int) -> Int
Ale okazuje się, że nie mogę go już zaimplementować: ponieważ IO
w wyniku tego funkcja argumentu nie może go użyć w sobie 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
Jedynym sposobem, w jaki mógłbym użyć IO
akcji foo
jest to, że wynik foo
ma IO Int
sam typ :
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Ale w tym momencie z podpisu jasno wynika, foo
że nie jest to również czysta funkcja.
foo = function(function bar){ print(bar.toString()) }