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