Như Telastyn đã nói: Về mặt kỹ thuật, có, trừ khi có một số cách trong ngôn ngữ của bạn để đảm bảo rằng chức năng đầu vào cũng thuần túy.
Đó không phải là giả thuyết, thực sự có nhiều cách tốt để đảm bảo điều này. Ít nhất là trong một ngôn ngữ đánh máy mạnh mẽ.
Một hàm ~ thuần túy như vậy bạn sẽ viết bằng JavaScript như
function foo(f) {
return f(1) + 2;
}
có thể được dịch trực tiếp sang Haskell:
foo :: (Int -> Int) -> Int
foo f = f 1 + 2
Bây giờ, trong JavaScript, bạn có thể làm những thứ xấu xa như
js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2
Điều này là không thể trong Haskell . Lý do là, một cái gì đó có tác dụng phụ giống như console.log()
luôn phải có một loại kết quả IO something
, không chỉ something
một mình.
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)
Để biểu thức này được đánh máy, chúng ta sẽ cần cung cấp foo
chữ ký loại
foo :: (Int -> IO Int) -> Int
Nhưng hóa ra tôi không thể thực hiện nó nữa: vì hàm đối số có IO
trong kết quả của nó, tôi không thể sử dụng nó trong 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
Cách duy nhất tôi có thể sử dụng một IO
hành động foo
là nếu kết quả của chính nó foo
có loại IO Int
:
foo :: (Int -> IO Int) -> IO Int
foo f = do
f1 <- f 1
return (f1 + 2)
Nhưng tại thời điểm này, rõ ràng từ chữ ký của foo
nó cũng không phải là một chức năng thuần túy.
foo = function(function bar){ print(bar.toString()) }