正如Telastyn所说:从技术上讲,是的,除非您的语言中有某种方法可以保证输入函数也是纯函数。
那不是假设,确实有很好的方法可以保证这一点。至少使用强类型语言。
您可以在JavaScript中编写的如此纯函数
function foo(f) {
return f(1) + 2;
}
可以直接翻译为Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
现在,在JavaScript中,您可以做诸如
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
在Haskell中这是不可能的。原因是,类似副作用的东西console.log()
必须始终具有结果类型IO something
,而不仅仅是一个结果类型something
。
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)
为了对此表达式进行foo
类型检查,我们需要提供类型签名
foo :: (Int -> IO Int) -> Int
但是事实证明我不能再实现它了:因为参数函数包含IO
在结果中,所以我不能在中使用它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
我可以在其中使用IO
操作的唯一方法foo
是,如果的结果本身foo
具有类型IO Int
:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
但是从签名的角度来看foo
,这显然不是一个纯函数。
foo = function(function bar){ print(bar.toString()) }