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