Haskell을 배우는 동안 Haskell에서 비롯된 훌륭한 발명품 인 클래스 클래스를 발견했습니다 .
그러나 클래스 유형의 Wikipedia 페이지에서 :
프로그래머는 클래스에 속하는 모든 유형에 대해 존재해야하는 함수 또는 상수 이름 세트를 해당 유형과 함께 지정하여 유형 클래스를 정의합니다.
나에게 Java의 인터페이스 에 다소 가까운 것 같습니다 ( Wikipedia의 Interface (Java) 페이지 인용 ).
Java 프로그래밍 언어의 인터페이스는 클래스가 구현해야하는 인터페이스 (일반적인 의미에서)를 지정하는 데 사용되는 추상 유형입니다.
이 두 가지는 다소 비슷해 보입니다. 유형 클래스는 유형의 동작을 제한하는 반면 인터페이스는 클래스의 동작을 제한합니다.
Haskell의 유형 클래스와 Java의 인터페이스 간의 차이점과 유사점이 무엇인지 궁금합니다. 아니면 근본적으로 다른 것일까 요?
편집 : 나는 심지어 haskell.org가 그들이 비슷하다는 것을 인정한다는 것을 알았습니다 . 그들이 그렇게 비슷하다면 (또는 그들이 있습니까?), 왜 타입 클래스가 그러한 과장으로 취급됩니까?
추가 편집 : 와우, 너무 많은 훌륭한 답변이 있습니다! 커뮤니티가 어느 것이 가장 좋은지 결정하도록해야 할 것 같습니다. 그러나 대답을 읽는 동안 그들 모두는 “인터페이스가 제네릭에 대처할 수 없거나 대처해야하는 동안 typeclass가 할 수있는 많은 일이있다”고만 말하는 것처럼 보입니다 . 나는 도울 수 없지만 궁금해 할 수 있습니다. 유형 클래스가 할 수없는 동안 인터페이스가 할 수있는 것이 있습니까? 또한 Wikipedia에서 typeclass가 원래 1989 년 논문 * “임시 다형성을 덜 임시로 만드는 방법”에서 발명되었다고 주장하는 반면 Haskell은 여전히 요람에 있으며 Java 프로젝트는 1991 년에 시작되어 1995 년에 처음 출시되었습니다. 그래서 아마도 typeclass가 인터페이스와 유사한 대신에, 그 반대의 경우 인터페이스가 typeclass의 영향을 받았습니까?이를 뒷받침하거나 반박하는 문서 / 문서가 있습니까? 모든 답변에 감사드립니다. 그들은 모두 매우 깨달았습니다!
모든 입력에 감사드립니다!
답변
인터페이스는 SomeInterface t
모든 값이 유형을 갖는 유형 클래스와 비슷하다고 말할 수 있습니다 t -> whatever
(여기서는 whatever
포함하지 않음 t
). 이는 Java 및 유사한 언어의 상속 관계의 종류로 인해 호출되는 메서드가 호출되는 객체 유형에 따라 달라지며 다른 것은 없기 때문입니다.
즉 add :: t -> t -> t
, 인터페이스가 하나 이상의 매개 변수에 대해 다형성 인 인터페이스와 같은 것을 만드는 것은 정말 어렵다는 것을 의미합니다 . 왜냐하면 인터페이스가 메소드의 인수 유형과 반환 유형이 메소드의 유형과 동일한 유형임을 지정할 방법이 없기 때문입니다. 호출 된 객체 (예 : “self”유형). 제네릭으로, 객체 자체와 같은 형태가 될 것으로 예상된다 일반적인 매개 변수 인터페이스를함으로써 가짜 이에 대한 방법이 좀있다, 방법처럼 Comparable<T>
그것을 않습니다, 당신이 사용할 것으로 예상되는 곳 Foo implements Comparable<Foo>
이므로 것을 compareTo(T otherobject)
의 종류 유형이t -> t -> Ordering
. 하지만 그래도 프로그래머는이 규칙을 따라야하며, 사람들이이 인터페이스를 사용하는 함수를 만들고자 할 때 골칫거리가되고 재귀 적 제네릭 유형 매개 변수가 있어야합니다.
또한 empty :: t
여기에서 함수를 호출하지 않기 때문에 같은 것이 없기 때문에 메서드가 아닙니다.
답변
인터페이스와 유형 클래스의 유사한 점은 관련 작업 집합의 이름을 지정하고 설명한다는 것입니다. 작업 자체는 이름, 입력 및 출력을 통해 설명됩니다. 마찬가지로 이러한 작업의 구현이 다를 수있는 많은 구현이있을 수 있습니다.
이를 통해 몇 가지 주목할만한 차이점이 있습니다.
- 인터페이스 메서드는 항상 개체 인스턴스와 연결됩니다. 즉, 메서드가 호출되는 객체 인 암시 적 ‘this’매개 변수가 항상 있습니다. 유형 클래스 함수에 대한 모든 입력은 명시 적입니다.
- 인터페이스 구현은 인터페이스를 구현하는 클래스의 일부로 정의되어야합니다. 반대로, 유형 클래스 ‘인스턴스’는 다른 모듈에서도 관련 유형과 완전히 분리되어 정의 될 수 있습니다.
일반적으로 타입 클래스가 인터페이스보다 강력하고 유연하다고 말하는 것이 공정하다고 생각합니다. 문자열을 구현 유형의 값 또는 인스턴스로 변환하기위한 인터페이스를 어떻게 정의 하시겠습니까? 확실히 불가능하지는 않지만 결과는 직관적이거나 우아하지 않습니다. 컴파일 된 라이브러리에서 유형에 대한 인터페이스를 구현할 수 있기를 바란 적이 있습니까? 둘 다 유형 클래스로 쉽게 수행 할 수 있습니다.
답변
유형 클래스는 기본적으로 오버로드 된 함수 의 기술 용어 인 “임시 다형성”을 표현하는 구조화 된 방법으로 생성되었습니다 . 유형 클래스 정의는 다음과 같습니다.
class Foobar a where
foo :: a -> a -> Bool
bar :: String -> a
이것이 의미하는 바는 foo
클래스에 속하는 유형의 일부 인수에 함수 를 적용 할 때 해당 유형 Foobar
에 foo
특정한 구현을 찾아서 사용한다는 것입니다. 이것은 더 유연하고 일반화 된 것을 제외하고는 C ++ / C #과 같은 언어에서 연산자 오버로딩이있는 상황과 매우 유사합니다.
인터페이스는 OO 언어에서 비슷한 목적을 제공하지만 기본 개념은 약간 다릅니다. OO 언어는 Haskell이 가지고 있지 않은 유형 계층 구조의 기본 제공 개념과 함께 제공됩니다. 이는 인터페이스가 하위 유형 지정 (예 : 적절한 인스턴스에서 메서드 호출, 인터페이스를 구현하는 하위 유형의 상위 유형 수행)에 의한 오버로딩을 모두 포함 할 수 있기 때문에 어떤면에서 문제를 복잡하게 만듭니다. 플랫 타입 기반 디스패치 (인터페이스를 구현하는 두 클래스가 인터페이스를 구현하는 공통 수퍼 클래스가 없을 수 있기 때문에)에 의해. 서브 타이핑에 의해 도입 된 엄청난 추가 복잡성을 감안할 때, 유형 클래스를 비 OO 언어에서 오버로드 된 함수의 개선 된 버전으로 생각하는 것이 더 유용하다고 제안합니다.
또한 주목할 가치가있는 것은 타입 클래스는 훨씬 더 유연한 디스패치 수단을 가지고 있다는 것입니다. 인터페이스는 일반적으로 그것을 구현하는 단일 클래스에만 적용되는 반면 타입 클래스는 클래스 함수의 시그니처 어디에나 나타날 수 있는 타입에 대해 정의 됩니다. OO 인터페이스에서 이와 동등한 것은 인터페이스가 해당 클래스의 객체를 다른 클래스에 전달하는 방법을 정의하고, 어떤 반환 유형을 기반으로 구현을 선택하는 정적 메서드 및 생성자를 정의하도록 허용하는 것입니다. , 호출 컨텍스트에서 필요한 정의하고, 인터페이스를 구현하는 클래스와 동일한 유형의 인수 및 실제로 전혀 번역되지 않는 다양한 기타 항목을 가져옵니다.
요컨대 : 그들은 비슷한 목적을 제공하지만 작동 방식이 다소 다르며 유형 클래스는 모두 훨씬 더 표현력이 뛰어나고 경우에 따라 상속 계층 구조의 일부가 아닌 고정 유형에서 작업하기 때문에 사용하기가 더 간단합니다.
답변
위의 답변을 읽었습니다. 조금 더 명확하게 대답 할 수 있다고 생각합니다.
Haskell “유형 클래스”와 Java / C # “인터페이스”또는 Scala “특성”은 기본적으로 유사합니다. 그들 사이에는 개념적 차이가 없지만 구현 차이가 있습니다.
- Haskell 유형 클래스는 데이터 유형 정의와 분리 된 “인스턴스”로 구현됩니다. C # / Java / Scala에서 인터페이스 / 특성은 클래스 정의에서 구현되어야합니다.
- Haskell 유형 클래스를 사용하면이 유형 또는 자체 유형을 반환 할 수 있습니다. 스칼라 특성도 마찬가지입니다 (this.type). Scala의 “자체 유형”은 완전히 관련이없는 기능입니다. Java / C #에서는이 동작을 근사화하기 위해 제네릭을 사용하는 복잡한 해결 방법이 필요합니다.
- Haskell 유형 클래스를 사용하면 입력 “this”유형 매개 변수없이 함수 (상수 포함)를 정의 할 수 있습니다. Java / C # 인터페이스 및 Scala 특성에는 모든 함수에 “this”입력 매개 변수가 필요합니다.
- Haskell 유형 클래스를 사용하면 함수에 대한 기본 구현을 정의 할 수 있습니다. Scala 특성과 Java 8+ 인터페이스도 마찬가지입니다. C #은 확장 메서드를 사용하여 이와 유사하게 만들 수 있습니다.
답변
에서 프로그램의 마스터 마음 , 하스켈에서 자바 인터페이스 및 유형 클래스 사이의 유사성을 설명 할 필 Wadler 입력 클래스의 발명자와 하스켈에 대한 인터뷰가있다 :
다음과 같은 Java 메소드 :
public static <T extends Comparable<T>> T min (T x, T y) { if (x.compare(y) < 0) return x; else return y; }
Haskell 방법과 매우 유사합니다.
min :: Ord a => a -> a -> a min x y = if x < y then x else y
따라서 유형 클래스는 인터페이스와 관련이 있지만 실제 대응은 위와 같은 유형으로 매개 변수화 된 정적 메소드입니다.
답변
Phillip Wadler의 Faith, Evolution 및 프로그래밍 언어 강연을 시청하십시오 . Wadler는 Haskell에서 일했으며 Java Generics의 주요 기여자였습니다.
답변
인터페이스가 할 수없는 여러 문제를 유형 클래스로 해결할 수있는 방법에 대한 예제가 제공되는 소프트웨어 확장 및 유형 클래스와의 통합을 읽어보십시오 .
논문에 나열된 예는 다음과 같습니다.
- 표현 문제,
- 프레임 워크 통합 문제,
- 독립적 인 확장 성 문제,
- 지배적 인 분해, 산란 및 엉킴의 폭정.