В чем разница между чертами в Rust и typeclasses в Haskell?


черт в Русте, кажется, по крайней мере, внешне похожая на typeclasses в Haskell, однако я видел, как люди пишут, что между ними есть некоторые различия. Мне было интересно, в чем именно заключаются эти различия.

3 114

3 ответа:

на базовом уровне нет большой разницы, но они все еще там.

Haskell описывает функции или значения, определенные в классе типов как "методы", так же как черты описывают методы ООП в объектах, которые они заключают. Однако Haskell имеет дело с ними по-разному, рассматривая их как индивидуальные значения, а не привязывая их к объекту, как это сделал бы ООП. Это примерно самая очевидная разница в уровне поверхности.

единственное, что ржавеет не мог сделать, до недавнего времени, был типизированные черты высшего порядка, например, печально известный Functor и Monad typeclasses.

сопутствующие товары.* Однако это не идиоматическая ржавчина, и обычно считается "взломом".

также можно упомянуть, как сказано в комментариях, что GHC (основной компилятор Haskell) поддерживает дополнительные параметры для typeclasses, включая Multi-параметра (т. е. много видов) классов типов, и функциональных зависимостей, прекрасный вариант, который позволяет для вычислений на уровне типа, и приводит к семей типа. Насколько мне известно, у Rust нет ни funDeps, ни семейств типов, хотя это может произойти в будущем.†

в целом, хотя черты и типы могут казаться эквивалентными на поверхности, они имеют много различий при сравнении более глубоко, при рассмотрении многочисленных качество.


* на боковой ноте Swift, несмотря на наличие черт, не имеет такого механизма более высокого типа. Может быть, будущее обновление языка?

† хорошая статья о типах Haskell (в том числе с более высоким типом) можно найти здесь, и столь же хороший на чертах ржавчины сохраняется здесь, хотя, к сожалению, немного устарели.

"черты" Руста аналогичны классам типа Хаскелла.

основное отличие от Haskell заключается в том, что признаки вмешиваются только для выражений с точечной нотацией, т. е. формы a.foo(b).

классы типа Haskell распространяются на типы более высокого порядка. Признаки ржавчины только не поддерживают типы более высокого порядка, потому что они отсутствуют во всем языке, т. е. это не философское различие между признаками и классами типов

Я думаю, что текущие ответы упускают из виду самые фундаментальные различия между признаками ржавчины и классами типа Haskell. Эти различия связаны с тем, как черты связаны с объектно-ориентированными языковыми конструкциями. Для получения информации об этом см. книга ржавчина.

  1. объявление признака создает тип признака. Это означает, что вы можете объявить переменные такого типа (или, скорее, ссылки на тип). Вы также можете использовать типы признаков в качестве параметров для функций, полей структуры и экземпляров параметров типа.

    ссылочная переменная признака может во время выполнения содержать объекты различных типов, если тип среды выполнения ссылочного объекта реализует признак.

    // The shape variable might contain a Square or a Circle, 
    // we don't know until runtime
    let shape: &Shape = get_unknown_shape();
    
    // Might contain different kinds of shapes at the same time
    let shapes: Vec<&Shape> = get_shapes();
    

    это не то, как работают классы типов. классы типов не создают типов, так что вы не можете объявлять переменные с именем класса. классы типов действуют как границы по параметрам типа, но тип параметры должны быть созданы с конкретным типом, а не с самим классом типа.

    вы не можете иметь список различных вещей разных типов, которые реализуют один и тот же тип класса. (Вместо этого экзистенциальные типы используются в Haskell для выражения аналогичной вещи.)

  2. методы признака могут быть динамически распределяемых. Это сильно связано с тем, что описано выше пуля.

    динамическая отправка означает, что среда выполнения тип объекта опорные точки используются для определения того, какой метод вызывается через ссылку.

    let shape: &Shape = get_unknown_shape();
    
    // This calls a method, which might be Square.area or
    // Circle.area depending on the runtime type of shape
    print!("Area: {}", shape.area());
    

    опять же, экзистенциальные типы используются для этого в Haskell.

В Заключение

мне кажется, что черты по существу являются тем же понятием, что и классы типов. Кроме того, они имеют функциональность объектно-ориентированных интерфейсов.

(классы типов Haskell являются более продвинутыми, так как Haskell имеет, например более высокие типы и расширения, такие как многопараметрические классы типов. Но я думаю, что они по сути одинаковы.)