한 언어에서는 다른 언어보다 쉬울 수도 있고 어려운 것이 있지만 한 언어에서는 가능하고 다른 언어에서는 불가능하거나 관련이없는 유형 관련 기능에만 관심이 있습니다. 좀 더 구체적으로 말하면, 모든 종류의 미친 / 멋진 일을하는 많은 사람들이 있기 때문에 Haskell 유형 확장을 무시합시다.
한 언어에서는 다른 언어보다 쉬울 수도 있고 어려운 것이 있지만 한 언어에서는 가능하고 다른 언어에서는 불가능하거나 관련이없는 유형 관련 기능에만 관심이 있습니다. 좀 더 구체적으로 말하면, 모든 종류의 미친 / 멋진 일을하는 많은 사람들이 있기 때문에 Haskell 유형 확장을 무시합시다.
답변:
(여기서 사용 된 "Java"는 표준 Java SE 7 로 정의되며 여기에서 사용 된 "Haskell"은 표준 Haskell 2010으로 정의됩니다 .)
Java 타입 시스템에는 있지만 Haskell에는없는 것들 :
Haskell의 타입 시스템에는 있지만 Java에는없는 것들 :
편집하다:
위에 나열된 각 포인트의 예 :
/* 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'
-- 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에 (확장되지 않은) 프린시 펄 타이핑이 존재한다는 것은 완전한 타입 추론 (즉, 타입 주석 없이도 모든 표현식에 대해 성공적인 타입 추론)을 가능하게하는 것입니다. 주 입력을 손상시키는 확장 (많은 것이 있음)도 형식 유추의 완전성을 손상시킵니다.
l
단일 문자 변수로 사용하지 마십시오. 구분하기 가 매우 어렵습니다 1
!
Typeable
. 그러나 Haskell 2010에는 없습니다 (아마도 Haskell 2014는?).
자바의 타입 시스템에는 더 높은 종류의 다형성이 없다. 하스켈 타입 시스템이 있습니다.
즉, Java에서는 형식 생성자가 형식에 대해서는 추상화 할 수 있지만 형식 생성자에 대해서는 추상화 할 수 없지만 Haskell에서는 형식 생성자가 형식뿐만 아니라 형식 생성자에 대해서도 추상화 할 수 있습니다.
영어로 : Java에서 제네릭은 다른 제네릭 유형을 가져 와서 매개 변수화 할 수 없습니다.
public void <Foo> nonsense(Foo<Integer> i, Foo<String> j)
Haskell에서 이것은 매우 쉽습니다.
higherKinded :: Functor f => f Int -> f String
higherKinded = fmap show
<T<_> extends Collection> T<Integer> convertStringsToInts(T<string> strings)
. 여기서 아이디어는 누군가가 그것을 호출하면 convertStringsToInts<ArrayList>
문자열의 배열 목록을 가져 와서 정수의 배열 목록을 반환한다는 것입니다. 그리고 대신을 사용 convertStringsToInts<LinkedList>
하면 연결된 목록과 동일합니다.
forall
당신의 타입을 넣을 수있는 곳에서 높은 순위의 다형성에 관심이 있다는 것입니다 . Haskell에서 형식 a -> b
은 암시 적으로 forall a. forall b. a -> b
입니다. 확장 기능을 사용하면 이러한 forall
s를 명시 적으로 만들고 이동할 수 있습니다.
다른 답변을 보완하기 위해 Haskell의 유형 시스템에는 하위 유형이 없지만 Java와 같은 유형의 객체 지향 언어가 있습니다.
에서는 프로그래밍 언어 이론 , 하위 유형은 (또한 다형 서브 타입 또는 포접 다형 의 형태) 형 다형 되는 서브 타입 A는 데이터 유형 다른 데이터 유형 (받는 관련된 수퍼 일부 개념에 의해) 대체 가능성 전형적 서브 루틴들, 그 프로그램의 구성 요소를 의미, 또는 수퍼 타입의 요소들에 작용하도록 작성된 기능들은 또한 서브 타입의 요소들에 작용할 수있다. S가 T의 하위 유형 인 경우 하위 유형 관계는 종종 S <: T로 작성됩니다. 즉, S 유형의 모든 용어를 사용할 수 있는 컨텍스트에서 안전하게 사용할 수 있습니다 .유형 T의 용어가 예상됩니다. 서브 타이핑의 정확한 의미는 결정적으로 주어진 프로그래밍 언어에서 "어느 상황에서 안전하게 사용되는지"의 세부 사항에 달려 있습니다. 프로그래밍 언어 의 타입 시스템 은 본질적으로 자체 서브 타이핑 관계를 정의하는데, 이는 사소한 것일 수도 있습니다.
서브 타이핑 관계로 인해 용어는 둘 이상의 유형에 속할 수 있습니다. 따라서 서브 타이핑은 다형성 유형입니다. 객체 지향 프로그래밍에서 '다형성'이라는 용어는 일반적으로이 하위 유형 다형성 만을 지칭하는 데 사용되는 반면 파라 메트릭 다형성 기술은 일반 프로그래밍 으로 간주됩니다 ...
지금까지 아무도 언급하지 않은 한 가지 유형은 유추입니다. Haskell 컴파일러는 일반적으로 표현식 유형을 유추 할 수 있지만 Java 컴파일러에 유형을 자세히 알려야합니다. 엄밀히 말하면 이것은 컴파일러의 기능이지만 언어 및 유형 시스템의 디자인에 따라 유형 유추가 가능한지 여부가 결정됩니다. 특히 형식 유추는 Java의 하위 유형 다형성 및 임시 오버로드와 심하게 상호 작용합니다. 대조적으로, Haskell의 설계자들은 타입 추론에 영향을주는 기능들을 도입하지 않으려 고 노력합니다.
사람들이 지금까지 언급하지 않은 또 다른 것은 대수적 데이터 유형입니다. 즉, 다른 유형의 합계 ( 'or')와 곱 ( 'and')에서 유형을 구성하는 기능입니다. Java 클래스는 제품 (필드 a 및 필드 b)을 잘 수행합니다. 그러나 그들은 실제로 합계를하지 않습니다 (필드 a OR 필드 b). 스칼라는 이것을 여러 사례 클래스로 인코딩해야하지만, 동일하지는 않습니다. 그리고 스칼라에서 작동하는 동안 Java가 가지고 있다고 말하는 것은 약간의 확장입니다.
Haskell은 함수 생성자->를 사용하여 함수 유형을 구성 할 수도 있습니다. Java의 메소드에는 유형 서명이 있지만이를 결합 할 수는 없습니다.
Java 타입 시스템은 Haskell이 갖지 못한 모듈 타입을 가능하게합니다 . Haskell을위한 OSGi가 있기까지는 시간이 걸릴 것입니다.