Як сказав Теластин: Технічно, так, якщо у вашій мові немає способу гарантувати, що функція введення також є чистою.
Це не гіпотетично, дійсно є хороші способи гарантувати це. Принаймні сильно набраною мовою.
Таку чисту функцію ~ ви б написали в 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()) }