Wie Telastyn sagte: Technisch gesehen ja, es sei denn, es gibt einen Weg in Ihrer Sprache, um sicherzustellen, dass die Eingabefunktion auch rein ist.
Das ist nicht hypothetisch, es gibt in der Tat gute Möglichkeiten, dies zu garantieren. Zumindest in einer stark typisierten Sprache.
So eine reine ~ Funktion würden Sie in JavaScript als schreiben
function foo(f) {
return f(1) + 2;
}
kann direkt nach Haskell übersetzt werden:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Jetzt können Sie in JavaScript böse Dinge tun wie
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
Dies ist in Haskell nicht möglich . Der Grund dafür ist, dass etwas nebenwirkungsreiches console.log()
immer einen Ergebnistyp haben muss IO something
, nicht nur something
alleine.
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)
Für diesen Ausdruck typecheck, müssten wir geben foo
die Art Unterschrift
foo :: (Int -> IO Int) -> Int
Es stellt sich aber heraus, dass ich es dann nicht mehr implementieren kann: Da die Argumentfunktion IO
das Ergebnis hat, kann ich es nicht innerhalb verwenden 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
Die einzige Möglichkeit, in der ich eine IO
Aktion verwenden könnte, foo
ist, wenn das Ergebnis von foo
den Typ IO Int
selbst hat:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Aber an dieser Stelle wird aus der Signatur deutlich, foo
dass es sich auch nicht um eine reine Funktion handelt.
foo = function(function bar){ print(bar.toString()) }