Rust의 특성 은 Haskell의 형식 클래스 와 적어도 피상적으로 비슷해 보이지만 사람들은 그들 사이에 약간의 차이가 있다고 봅니다. 이러한 차이점이 무엇인지 정확히 궁금했습니다.
std::default
있고 다중 매개 변수 특성 정렬 작업 (기능 종속성의 유사체 포함)이지만 AFAIK는 특권을받는 첫 번째 매개 변수를 해결해야합니다. 그러나 HKT는 없습니다. 그들은 장래의 희망 목록에 있지만 아직 수평선에 있지 않습니다.
Rust의 특성 은 Haskell의 형식 클래스 와 적어도 피상적으로 비슷해 보이지만 사람들은 그들 사이에 약간의 차이가 있다고 봅니다. 이러한 차이점이 무엇인지 정확히 궁금했습니다.
std::default
있고 다중 매개 변수 특성 정렬 작업 (기능 종속성의 유사체 포함)이지만 AFAIK는 특권을받는 첫 번째 매개 변수를 해결해야합니다. 그러나 HKT는 없습니다. 그들은 장래의 희망 목록에 있지만 아직 수평선에 있지 않습니다.
답변:
기본 수준에는 큰 차이가 없지만 여전히 있습니다.
Haskell은 타입 클래스에 정의 된 함수 나 값을 '메소드'로 설명합니다. 특성이 객체에있는 OOP 메소드를 설명하는 것과 같습니다. 그러나 Haskell은 이러한 방식을 다르게 처리하여 OOP로 인해 객체에 고정하는 대신 개별 값으로 취급합니다. 이것은 가장 명백한 표면 수준의 차이입니다.
Rust가 한동안 할 수 없었던 한 가지는 악명 높은 타입 클래스 와 같은 고차 타입의 특성 이었습니다 .Functor
Monad
이는 녹 특성이 흔히 '콘크리트 유형', 즉 일반적인 논증이없는 것을 설명 할 수 있음을 의미합니다. Haskell은 처음부터 고차 함수가 다른 함수를 사용하는 것과 비슷한 유형을 사용하는 고차 타입 클래스를 만들 수 있습니다. 한동안 이것은 Rust에서 불가능했지만 관련 항목 이 구현되었으므로 그러한 특성은 평범하고 관용적이되었습니다.
따라서 확장을 무시하면 정확히 같지는 않지만 각각 확장 할 수 있습니다.
주석에서 언급했듯이 GHC (Haskell의 주요 컴파일러)는 다중 매개 변수 (예 : 많은 유형의 유형) 유형 클래스 및 유형 수준 계산을 허용하는 멋진 옵션 인 기능 종속성을 포함하여 유형 클래스에 대한 추가 옵션을 지원 한다고 언급 할 수 있습니다 그리고 유형 패밀리로 이어집니다 . 내 지식으로는 Rust는 funDeps 나 type family를 가지고 있지 않지만 장래에있을 수도 있습니다. †
대체로 특성과 유형 분류에는 근본적인 차이가 있습니다. 특성과 상호 작용하는 방식으로 인해 결국 행동과 유사하게 보입니다.
† Haskell의 타입 클래스 (고 타입 타입 포함)에 대한 좋은 기사는 여기 에서 볼 수 있고 , 특성에 관한 예제에 의한 Rust 장은 여기 에서 찾을 수 있습니다.
현재 답변이 Rust 특성과 Haskell 유형 클래스의 가장 근본적인 차이점을 간과한다고 생각합니다. 이러한 차이점은 특성이 객체 지향 언어 구성과 관련되는 방식과 관련이 있습니다. 이에 대한 정보는 Rust book을 참조하십시오 .
특성 선언은 특성 유형을 만듭니다 . 즉, 이러한 유형의 변수 (또는 유형의 참조)를 선언 할 수 있습니다. 특성, 구조체 필드 및 형식 매개 변수 인스턴스화에서 특성 유형을 매개 변수로 사용할 수도 있습니다.
특성 참조 변수는 런타임에 참조 된 오브젝트의 런타임 유형이 특성을 구현하는 한 다른 유형의 오브젝트를 포함 할 수 있습니다.
// 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에서는 실존 유형이 비슷한 것을 표현하기 위해 사용됩니다.) 주 1
특성 메소드는 동적으로 전달 될 수 있습니다 . 이것은 위 섹션에서 설명한 것과 밀접한 관련이 있습니다.
동적 디스패치는 참조를 통해 호출되는 메소드를 판별하기 위해 참조가 가리키는 오브젝트의 런타임 유형이 사용됨을 의미합니다.
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은 예를 들어 다중 매개 변수 유형 클래스와 같은 더 높은 종류의 유형과 확장을 가지고 있습니다.
참고 1 : 최신 버전의 Rust에는 특성 이름을 유형으로 사용하고 특성 이름을 경계로 사용하는 것을 구별하기 위해 업데이트되었습니다. 특성 유형에서 이름 앞에 dyn
키워드 가 붙습니다 . 자세한 내용은 예를 들어이 답변 을 참조하십시오.
dyn Trait
특성 / 유형 클래스와 관련되어 있기 때문에 실재 타이핑 형식 으로 이해하는 것이 가장 좋습니다 . dyn
유형에 투영하는 경계에 대한 연산자를 고려할 수 있습니다 dyn : List Bound -> Type
. 이 아이디어를 Haskell에 가져 가서 "클래스 이름으로 변수를 선언 할 수 없습니다"와 관련하여 Haskell에서 간접적으로 수행 할 수 있습니다 data Dyn (c :: * -> Constraint) = forall (t :: Type). c t => D t
. 이를 정의한 후 작업 할 수 있습니다 [D True, D "abc", D 42] :: [D Show]
.
Rust의“특성”은 Haskell의 유형 클래스와 유사합니다.
Haskell과의 주요 차이점은 특성이 점 표기법 (예 : a.foo (b) 형식)이있는 표현식에만 개입한다는 것입니다.
하스켈 타입 클래스는 고차 타입으로 확장됩니다. 녹 특성은 전체 언어에서 누락되기 때문에 고차 유형 만 지원하지 않습니다. 즉 특성과 유형 클래스 사이의 철학적 차이가 아닙니다.
Default
메소드가없고 메소드와 연관된 함수 만없는 특성을 고려하십시오 .
class Functor f where fmap :: (a -> b) -> (f a -> f b)
; 후자의 예는class Bounded a where maxBound :: a
입니다.