Помимо синтаксических проблем, самая большая разница заключается в системе типов и модели выполнения.
Как уже указала @senia, scala является строгим и не чистым, что не означает, что вы не можете писать чистые функции (вы можете сделать это и в C), просто компилятор не будет его применять.
Фреге, OTOH ленив и чист, что означает, что все нечистые эффекты вынуждены жить в монаде ST или IO. Система типов очень важна для Haskell 2010, с классами типов и дополнительными типами функций более высокого ранга. Вывод типов работает в масштабах всей программы, за исключением функций с типами более высокого ранга, в которых по крайней мере полиморфный аргумент должен быть аннотирован. Вот пример:
both f xs ys = (f xs, f ys)
Для этой функции компилятор определяет тип:
both :: (α->β) -> α -> α -> (β, β)
Обратите внимание, что оба xs
и ys
получают один и тот же тип из-за применения f
. Но теперь допустим, что мы хотим использовать функцию полиморфного списка, которую мы можем использовать с разными типами xs и ys. Например, мы хотим написать:
both reverse [1,2,3] ['a' .. 'z']
В его нынешнем виде это приложение будет ошибочным, потому что два списка имеют разные типы элементов и, следовательно, разные типы. Таким образом, компилятор откажется от списка символов.
К счастью, мы можем более точно сообщить компилятору, чего мы хотим, с помощью аннотации типа:
both :: (forall e.[e] -> [e]) -> [a] -> [b] -> ([a], [b])
Это говорит о следующем: мы передадим both
функцию, которая выполняет некоторое преобразование списка, но не заботится о типе элемента списка. Затем мы передаем 2 списка с возможно разными типами элементов. И мы получаем кортеж с нашими преобразованными списками обратно. Обратите внимание, что код both
изменять не нужно.
Другой способ добиться того же - написать:
both (f :: forall e.[e]->[e]) xs ys = (f xs, f ys)
а средство проверки типов делает вывод об остальном, а именно, что xs
и ys
должны быть списками, но могут иметь разные типы элементов.
Система типов Scalas полностью (насколько мне известно) поддерживает объектно-ориентированный подход. Хотя Frege поддерживает его лишь частично в отношении типов, импортированных для Java, но не поддерживает определение собственных объектно-ориентированных типов.
Следовательно, оба языка поддерживают функциональное программирование в среде JVM, хотя и в совершенно разных нишах. Третья ниша - это ниша с динамической типизацией, где Clojure является королем в мире JVM.
person
Ingo
schedule
28.07.2013