Haskell의 타입 시스템은 공식적으로 Java와 동일합니까? [닫은]


66

한 언어에서는 다른 언어보다 쉬울 수도 있고 어려운 것이 있지만 한 언어에서는 가능하고 다른 언어에서는 불가능하거나 관련이없는 유형 관련 기능에만 관심이 있습니다. 좀 더 구체적으로 말하면, 모든 종류의 미친 / 멋진 일을하는 많은 사람들이 있기 때문에 Haskell 유형 확장을 무시합시다.


4
나도 구식 카테고리 이론가들이이 질문에 대답하는 것을 듣고 궁금하다. 나는 그것을 특히 이해할 것이라고 의심하지만, 나는 이것에 대한 세부 사항에 여전히 관심이 있습니다. 내가 읽은 것들에서 내 성향은 HM 형 시스템은 컴파일러가 알 수 있다는 것입니다 코드가이 유형을 추론 너무 많이뿐만 아니라 행동에 대해 많은 보장을 제공 할 수있는 이유입니다 무엇에 대한합니다. 그러나 그것은 내 직감에 지나지 않으며, 나는 전혀 알지 못하는 다른 것들이 있다고 확신합니다.
Jimmy Hoffa

1
큰 질문입니다-위대한 Haskell / JVM 토론을 위해 추종자들에게 트윗 할 시간입니다!
Martijn Verburg

6
@ m3th0dman : Scala는 Java와 동일한 고차 함수를 정확히 지원합니다. 스칼라에서 퍼스트 클래스 함수는 Java와 마찬가지로 단일 추상 메소드를 사용하여 추상 클래스의 인스턴스로 간단히 표현됩니다. 물론 스칼라는 이러한 함수를 정의하는 구문 설탕을 가지고 있으며 함수를 받아들이는 미리 정의 된 함수 유형과 메소드 모두의 풍부한 표준 라이브러리를 가지고 있지만 유형 시스템의 관점 에서 볼 때 ,이 질문에 관한 차이점은 없습니다. . 스칼라가 할 수 있다면 Java도 할 수 있으며 실제로 Java 용 Haskell에서 영감을 얻은 FP 라이브러리가 있습니다.
Jörg W Mittag

2
@ m3th0dman : 그것은이 질문에 관한 것이 아닙니다.
Phil

7
@ m3th0dman 완벽하게 평범한 유형입니다. 일부 구문 론적 인 장점을 제외하고 목록에는 특별한 것이 없습니다. 리터럴 구문과 생성자의 이름을 제외하고 내장 목록 유형과 동등한 고유 한 대수 데이터 유형을 쉽게 정의 할 수 있습니다.
sepp2k

답변:


63

(여기서 사용 된 "Java"는 표준 Java SE 7 로 정의되며 여기에서 사용 된 "Haskell"은 표준 Haskell 2010으로 정의됩니다 .)

Java 타입 시스템에는 있지만 Haskell에는없는 것들 :

  • 공칭 아형 다형성
  • 부분 런타임 유형 정보

Haskell의 타입 시스템에는 있지만 Java에는없는 것들 :

  • 경계 임시 다형성
    • "제약 기반"하위 유형 다형성을 발생시킵니다.
  • 더 높은 종류의 파라 메트릭 다형성
  • 주요한 타이핑

편집하다:

위에 나열된 각 포인트의 예 :

자바 고유 (Haskell과 비교)

공칭 아형 다형성

/* declare explicit subtypes (limited multiple inheritance is allowed) */
abstract class MyList extends AbstractList<String> implements RandomAccess {

    /* specify a type's additional initialization requirements */
    public MyList(elem1: String) {
        super() /* explicit call to a supertype's implementation */
        this.add(elem1) /* might be overridden in a subtype of this type */
    }

}

/* use a type as one of its supertypes (implicit upcasting) */
List<String> l = new ArrayList<>() /* some inference is available for generics */

부분 런타임 유형 정보

/* find the outermost actual type of a value at runtime */
Class<?> c = l.getClass // will be 'java.util.ArrayList'

/* query the relationship between runtime and compile-time types */
Boolean b = l instanceOf MyList // will be 'false'

Haskell 고유 (Java와 비교)

경계 애드혹 다형성

-- declare a parametrized bound
class A t where
  -- provide a function via this bound
  tInt :: t Int
  -- require other bounds within the functions provided by this bound
  mtInt :: Monad m => m (t Int)
  mtInt = return tInt -- define bound-provided functions via other bound-provided functions

-- fullfill a bound
instance A Maybe where
  tInt = Just 5
  mtInt = return Nothing -- override defaults

-- require exactly the bounds you need (ideally)
tString :: (Functor t, A t) => t String
tString = fmap show tInt -- use bounds that are implied by a concrete type (e.g., "Show Int")

"제한 기반"하위 유형 다형성 (경계 된 임시 다형성을 기반으로 함)

-- declare that a bound implies other bounds (introduce a subbound)
class (A t, Applicative t) => B t where -- bounds don't have to provide functions

-- use multiple bounds (intersection types in the context, union types in the full type)
mtString :: (Monad m, B t) => m (t String)
mtString = return mtInt -- use a bound that is implied by another bound (implicit upcasting)

optString :: Maybe String
optString = join mtString -- full types are contravariant in their contexts

고급 파라 메트릭 다형성

-- parametrize types over type variables that are themselves parametrized
data OneOrTwoTs t x = OneVariableT (t x) | TwoFixedTs (t Int) (t String)

-- bounds can be higher-kinded, too
class MonadStrip s where
  -- use arbitrarily nested higher-kinded type variables
  strip :: (Monad m, MonadTrans t) => s t m a -> t m a -> m a

주요한 타이핑

이것은 직접적인 예를 제시하기는 어렵지만 모든 표현에는 정확히 하나의 최대 일반 유형 ( 주요 유형 이라고 함 )이 있으며 이는 해당 표현의 표준 유형으로 간주됩니다. "제약 기반"하위 유형 다형성 (상기 참조)의 관점에서, 표현의 주요한 유형은 그 표현이 사용될 수있는 모든 가능한 유형의 고유 한 하위 유형입니다. Haskell에 (확장되지 않은) 프린시 펄 타이핑이 존재한다는 것은 완전한 타입 추론 (즉, 타입 주석 없이도 모든 표현식에 대해 성공적인 타입 추론)을 가능하게하는 것입니다. 주 입력을 손상시키는 확장 (많은 것이 있음)도 형식 유추의 완전성을 손상시킵니다.


7
l단일 문자 변수로 사용하지 마십시오. 구분하기 가 매우 어렵습니다 1!
recursion.ninja

5
Java에는 런타임 유형 정보가 있고 Haskell에는없는 것이 절대적으로 옳지 만 Haskell의 Typeable 유형 클래스를 사용하여 많은 유형에 대한 런타임 유형 정보와 같은 동작을 제공 할 수 있습니다 (최신 PolyKinded 사용) 클래스는 실제로 모든 유형 iirc입니다). 실제로 런타임에 유형 정보를 전달하는지 여부에 따라 상황에 따라 다릅니다.

3
@DarkOtter 알고 있습니다 Typeable. 그러나 Haskell 2010에는 없습니다 (아마도 Haskell 2014는?).
Ptharien 's Flame

5
(폐쇄) 합계 유형은 어떻습니까? 그것들은 인코딩 제약 조건에 대한 가장 중요한 메커니즘 중 하나입니다.
tibbe

3
무감각? 건전성 (공분산 실린 없음)? 결산 합계 유형 / 패턴 일치? 이 답변은 너무 좁습니다
Peaker

32

자바의 타입 시스템에는 더 높은 종류의 다형성이 없다. 하스켈 타입 시스템이 있습니다.

즉, Java에서는 형식 생성자가 형식에 대해서는 추상화 할 수 있지만 형식 생성자에 대해서는 추상화 할 수 없지만 Haskell에서는 형식 생성자가 형식뿐만 아니라 형식 생성자에 대해서도 추상화 할 수 있습니다.

영어로 : Java에서 제네릭은 다른 제네릭 유형을 가져 와서 매개 변수화 할 수 없습니다.

public void <Foo> nonsense(Foo<Integer> i, Foo<String> j)

Haskell에서 이것은 매우 쉽습니다.

higherKinded :: Functor f => f Int -> f String
higherKinded = fmap show

28
이번에 영어로 다시 실행 해 주시겠습니까? : P
Mason Wheeler

8
@Matt : 예를 들어 Java로 작성할 수는 없지만 Haskell에서 동등한 것을 작성할 수 있습니다 <T<_> extends Collection> T<Integer> convertStringsToInts(T<string> strings). 여기서 아이디어는 누군가가 그것을 호출하면 convertStringsToInts<ArrayList>문자열의 배열 목록을 가져 와서 정수의 배열 목록을 반환한다는 것입니다. 그리고 대신을 사용 convertStringsToInts<LinkedList>하면 연결된 목록과 동일합니다.
sepp2k

8
이 등급이 높은 다형성이 아닌 순위 1 대 n이 아닌가?
Adam

8
@ JörgWMittag : 제 이해는 당신이 forall당신의 타입을 넣을 수있는 곳에서 높은 순위의 다형성에 관심이 있다는 것입니다 . Haskell에서 형식 a -> b은 암시 적으로 forall a. forall b. a -> b입니다. 확장 기능을 사용하면 이러한 foralls를 명시 적으로 만들고 이동할 수 있습니다.
Tikhon Jelvis

8
@Adam은 엄밀합니다. 높은 순위와 높은 종류는 완전히 다릅니다. GHC는 언어 확장을 통해 더 높은 등급의 유형 (예 : 모든 유형)을 수행 할 수도 있습니다. 자바는 더 높은 등급이나 더 높은 등급을 알지 못한다.
Ingo

11

다른 답변을 보완하기 위해 Haskell의 유형 시스템에는 하위 유형이 없지만 Java와 같은 유형의 객체 지향 언어가 있습니다.

에서는 프로그래밍 언어 이론 , 하위 유형은 (또한 다형 서브 타입 또는 포접 다형 의 형태) 형 다형 되는 서브 타입 A는 데이터 유형 다른 데이터 유형 (받는 관련된 수퍼 일부 개념에 의해) 대체 가능성 전형적 서브 루틴들, 그 프로그램의 구성 요소를 의미, 또는 수퍼 타입의 요소들에 작용하도록 작성된 기능들은 또한 서브 타입의 요소들에 작용할 수있다. S가 T의 하위 유형 인 경우 하위 유형 관계는 종종 S <: T로 작성됩니다. 즉, S 유형의 모든 용어를 사용할 수 있는 컨텍스트에서 안전하게 사용할 수 있습니다 .유형 T의 용어가 예상됩니다. 서브 타이핑의 정확한 의미는 결정적으로 주어진 프로그래밍 언어에서 "어느 상황에서 안전하게 사용되는지"의 세부 사항에 달려 있습니다. 프로그래밍 언어 의 타입 시스템 은 본질적으로 자체 서브 타이핑 관계를 정의하는데, 이는 사소한 것일 수도 있습니다.

서브 타이핑 관계로 인해 용어는 둘 이상의 유형에 속할 수 있습니다. 따라서 서브 타이핑은 다형성 유형입니다. 객체 지향 프로그래밍에서 '다형성'이라는 용어는 일반적으로이 하위 유형 다형성 만을 지칭하는 데 사용되는 반면 파라 메트릭 다형성 기술은 일반 프로그래밍 으로 간주됩니다 ...


4
그렇다고 ad-hoc 다형성을 얻지 못한다는 의미는 아닙니다. 당신은 다른 형식으로 (하위 유형 다형성 대신 유형 클래스) 있습니다.

3
서브 클래 싱은 서브 타입이 아닙니다!
Frank Shearar

8

지금까지 아무도 언급하지 않은 한 가지 유형은 유추입니다. Haskell 컴파일러는 일반적으로 표현식 유형을 유추 할 수 있지만 Java 컴파일러에 유형을 자세히 알려야합니다. 엄밀히 말하면 이것은 컴파일러의 기능이지만 언어 및 유형 시스템의 디자인에 따라 유형 유추가 가능한지 여부가 결정됩니다. 특히 형식 유추는 Java의 하위 유형 다형성 및 임시 오버로드와 심하게 상호 작용합니다. 대조적으로, Haskell의 설계자들은 타입 추론에 영향을주는 기능들을 도입하지 않으려 고 노력합니다.

사람들이 지금까지 언급하지 않은 또 다른 것은 대수적 데이터 유형입니다. 즉, 다른 유형의 합계 ( 'or')와 곱 ( 'and')에서 유형을 구성하는 기능입니다. Java 클래스는 제품 (필드 a 및 필드 b)을 잘 수행합니다. 그러나 그들은 실제로 합계를하지 않습니다 (필드 a OR 필드 b). 스칼라는 이것을 여러 사례 클래스로 인코딩해야하지만, 동일하지는 않습니다. 그리고 스칼라에서 작동하는 동안 Java가 가지고 있다고 말하는 것은 약간의 확장입니다.

Haskell은 함수 생성자->를 사용하여 함수 유형을 구성 할 수도 있습니다. Java의 메소드에는 유형 서명이 있지만이를 결합 할 수는 없습니다.

Java 타입 시스템은 Haskell이 갖지 못한 모듈 타입을 가능하게합니다 . Haskell을위한 OSGi가 있기까지는 시간이 걸릴 것입니다.


1
@MattFenwick, 귀하의 의견에 따라 세 번째 단락을 수정했습니다. 두 유형 시스템은 기능을 매우 다르게 취급합니다.
GarethR

ADT를 유형 시스템의 기능이라고하지 않습니다. OO 래퍼로 완전히 (어색한 경우) 에뮬레이션 할 수 있습니다.
leftaroundabout

@ leftaroundabout 나는 이것이 논란의 여지가 있다고 생각합니다. 예를 들어, 한 언어의 유형 시스템에 고유 한 것이 있지만 다른 언어의 디자인 패턴으로 구현 될 수 있습니다. 분명히, 기본 패턴과 비교하여 디자인 패턴 방식이 해결 방법입니다. 유형이 약한 시스템으로 인한 해결 방법.
Hi-Angel

선택한 답변은 '주요 유형'섹션에서 '완전한 유형 유추'를 언급했습니다. Java는 하위 유형 및 런타임 유형 정보로 합계를 에뮬레이션 할 수 있지만 합계가 유형 시스템의 전체적인 속성이 아니라는 것과 동일하지 않습니다.
Shelby Moore III
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.