As Telastyn said: Technically, yes, unless there is some way in your language to guarantee that the input function is also pure.
That's not hypothetical, there are indeed good ways to guarantee this. At least in a strongly typed language.
Such a pure~ function you'd write in JavaScript as
function foo(f) {
return f(1) + 2;
}
can be translated directly to Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Now, in JavaScript you can do evil stuff like
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
This is not possible in Haskell. The reason being, something side-effect-ful like console.log()
must always have a result type IO something
, not just something
alone.
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)
For this expression to typecheck, we would need to give foo
the type signature
foo :: (Int -> IO Int) -> Int
But it turns out I cannot implement it anymore then: because the argument function has IO
in its result, I can not use it within 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
The only way I could use an IO
action in foo
is if the result of foo
has type IO Int
itself:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
But at this point it's clear from the signature of foo
that it is not a pure function, either.
foo = function(function bar){ print(bar.toString()) }
foo = function(function bar) { return 3; }
is pure, and takes a function as an argument.toString()
(ie the one you would find on Java's Object).