스칼라에서 더 높은 종류의 유형은 무엇입니까?


275

웹에서 다음을 찾을 수 있습니다.

  1. 더 높은 종류의 유형 == 유형 생성자?

    class AClass[T]{...} // For example, class List[T]

    어떤 사람들은 이것이 정의에 부합하는 유형을 추상화하기 때문에 이것이 더 높은 종류의 유형이라고 말합니다.

    더 높은 종류의 유형 은 다른 유형을 취하여 새로운 유형을 구성하는 유형입니다.

    이것들은 타입 생성자 로도 알려져 있습니다 . (예를 들어, Scala 프로그래밍에서 ).

  2. 유형 생성자를 유형 매개 변수로 사용하는 더 높은 종류의 유형 == 유형 생성자?

    더 높은 종류 의 논문 제네릭에서 읽을 수 있습니다.

    ... 유형에 따라 추상화되는 유형에 대해 추상화되는 유형 ( '고급 유형') ... "

    그 제안

    class XClass[M[T]]{...} // or
    
    trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]

    더 높은 종류입니다.

따라서이를 염두에두고 형식 생성자 , 높은 종류의 형식형식 생성자를 형식 매개 변수로 사용하는 형식 생성자 를 구분하기가 어렵습니다 . 따라서 위의 질문입니다.


Landei의 Functor를 예로 추가했습니다.
Lutz

답변:


284

약간의 모호함을 가지고이 혼란을 시작해 보도록하겠습니다. 나는 사람들이 그것에 익숙한 경향이 있기 때문에 이것을 설명하기 위해 가치 수준에 비유를 사용하고 싶습니다.

형식 생성자는 형식을 "구성"하기 위해 형식 인수에 적용 할 수있는 형식입니다.

값 생성자는 값을 "구성"하기 위해 값 인수에 적용 할 수있는 값입니다.

값 생성자는 일반적으로 "함수"또는 "방법"이라고합니다. 이 "생성자"는 "다형성"이라고도하며 (다양한 "모양"의 "재료"를 구성하는 데 사용될 수 있기 때문에) 또는 "추상화"(다른 다형성 인스턴스화 사이의 변화에 ​​대해 추상화하기 때문에)입니다.

추상화 / 다형성의 맥락에서 1 차는 추상화의 "단일 사용"을 의미합니다. 타입에 대해 추상화하면 한 번만 추상화되지만 해당 유형 자체는 어떤 것도 추상화 할 수 없습니다. Java 5 제네릭은 1 차입니다.

위의 추상화 특성에 대한 1 차 해석은 다음과 같습니다.

형식 생성자는 적절한 형식을 "구성"하기 위해 적절한 형식 인수에 적용 할 수있는 형식입니다.

값 생성자는 적절한 값을 "구성"하기 위해 적절한 값 인수에 적용 할 수있는 값입니다.

value 1나 type 과 같은 추상화가 필요하지 않다는 것을 강조하기 위해 (나는 이것을 "제로 순서"라고 부를 수는 있지만 어디에서나 이것을 보지 못했다)) String보통 우리는 무언가가 "적절한"값 또는 타입이라고 말한다.

적절한 값은 인수를 기다리지 않는다는 의미에서 "즉시 사용 가능"합니다 (추상하지 않음). 그것들을 쉽게 인쇄 / 검사 할 수있는 값으로 생각하십시오 (함수를 직렬화하는 것은 부정 행위입니다!).

올바른 유형은 값을 분류하는 유형 (값 생성자를 포함)이며, 유형 생성자는 값을 분류하지 않습니다 (먼저 올바른 유형을 적용하려면 올바른 유형 인수에 적용해야 함). 유형을 인스턴스화하려면 적절한 유형이어야합니다 (그러나 충분하지는 않습니다). (추상 클래스이거나 액세스 권한이없는 클래스 일 수 있습니다.)

"고차"는 단순히 다형성 / 추상화의 반복 사용을 의미하는 일반적인 용어입니다. 다형성 유형과 값에 대해서도 같은 의미입니다. 구체적으로, 고차 추상화는 무언가를 추상화하는 무언가를 추상화합니다. 유형의 경우 "고급"이라는 용어는보다 일반적인 "고급"의 특수 목적 버전입니다.

따라서 우리의 특성화의 상위 버전은 다음과 같습니다.

형식 생성자는 형식 인수 (적절한 형식 또는 형식 생성자)에 적용하여 적절한 형식 (생성자)을 "구성"할 수있는 형식입니다.

값 생성자는 값 인수 (적절한 값 또는 값 생성자)에 적용하여 적절한 값 (생성자)을 "구성"할 수있는 값입니다.

따라서 "고차"는 단순히 "X에 대한 요약"이라고 말할 때 실제로 의미합니다! 요약 된 X것은 자체 "추상 권"을 잃지 않습니다. 원하는 모든 것을 추상화 할 수 있습니다. (그런데, 나는 여기서 "추상적"이라는 동사를 사용하여 다음을 의미한다 : 값이나 유형의 정의에 필수적이지 않은 것을 생략하여 추상화 사용자가 인수로 다양하게 제공 할 수 있도록하는 것 .)

다음은 적절한 1 차 및 고차 값과 유형에 대한 몇 가지 예 (Lutz의 전자 메일 질문에서 영감을 받음)입니다.

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

사용 된 클래스는 다음과 같이 정의되었습니다.

class String
class List[T]
class Functor[F[_]]

클래스 정의를 통한 간접적 인 것을 피하려면 스칼라에서 직접 표현할 수없는 익명 유형 함수를 어떻게 든 표현해야하지만 구문 유형 오버 헤드없이 구조적 유형을 사용할 수 있습니다 ( -스타일은 https : //.com/stackoverflow.com / users / 160378 / retronym afaik) :

익명 유형 함수를 지원하는 몇 가지 가상 버전의 스칼라에서는 예제에서 마지막 줄을 다음과 같이 단축 할 수 있습니다.

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(개인적으로, "고급 유형"에 대해 이야기 한 것을 후회하는 것은 유감입니다. 결국 유형일뿐입니다. 반드시 명확하게해야 할 때, "유형 생성자 매개 변수", "유형 생성자 멤버"와 같은 것을 말하는 것이 좋습니다. 올바른 유형에 대해서만 말하는 것이 아니라는 점을 강조하기 위해

ps : 문제를 더 복잡하게하기 위해, "다형성"은 다른 방법으로 모호 Forall T, T => T합니다. 구조 유형으로 작성 {def apply[T](x: T): T = x})




나는 그것을 더 높은 친절한 것으로 읽고 친절한 정신을 상상하고있다
Janac Meena 23.54

110

(이 답변은 그래픽 및 역사적 정보로 Adriaan Moors 답변을 꾸미려는 시도입니다.)

더 높은 종류의 유형은 2.5 이후 스칼라의 일부입니다.

  • 그 전에는 지금까지 자바처럼 스칼라는 유형 생성자 (Java에서 "generics")를 사용하여 유형 생성자에 대한 유형 매개 변수로 사용할 수 없었습니다. 예 :

     trait Monad [M[_]]

    불가능했다.

    Scala 2.5에서 타입 시스템은 타입을 더 높은 레벨 ( 타입 생성자 다형성 이라고 함)로 분류하는 기능으로 확장되었습니다 . 이러한 분류를 종류라고합니다.

    유형과 종류의 실현, "더 높은 종류의 유전학"에서 파생 된 ** ( 높은 종류의 제네릭 에서 파생 된 그림 )

    결과적으로 해당 유형 생성자 (예 :)는 유형 생성자의 List유형 매개 변수 위치에서 다른 유형과 같이 사용될 수 있으므로 Scala 2.5 이후로 1 등급 유형이되었습니다. (Scala의 일류 값인 함수와 유사).

    높은 종류지지 형 시스템의 관점에서, 우리는 구별 할 적절한 유형 , 종류 등 Int또는 List[Int]일차 같은 유형의 List그리고 높은 가지 유형 을 추천 Functor하거나 Monad(종류 종류 이상의 추상화 된 종류 이상의 추상된다).

    다른 쪽의 Java 유형 시스템은 종류를 지원하지 않으므로 "상위 종류"유형이 없습니다.

    따라서 이것은 지원 유형 시스템의 배경에서 볼 수 있습니다.

  • 스칼라의 경우 종종 다음과 같은 유형 생성자의 예를 볼 수 있습니다

     trait Iterable[A, Container[_]]

    제목이 "더 높은 종류의 유형"인 경우 (예 : 일반 프로그래머의 경우 Scala, 섹션 4.3)

    이것은 때때로 많은 사람들이 참조하기 때문에, missleading되는 Container높은 kinded 타입 이 아니라 Iterable, 더 정확하다, 그러나 무엇인가

    Container더 높은 종류의 (더 높은 차수) 형식의 형식 생성자 매개 변수로 사용 here Iterable.


80

인스턴스가 값인 and와 같은 일반 유형 의 종류 는 입니다. 같은 단항 타입 생성자의 종류 IS ; 이진 형식 생성자 는 ( curryed ) kind 등입니다. 유형 레벨 함수 와 같은 유형을 유형별로 볼 수 있습니다 . 하나 이상의 유형을 가져 와서 유형을 리턴합니다.IntChar*Maybe* -> *Either* -> * -> *MaybeEither

함수이다 고차 그것이 있다면 주문 순서 함수 화살표 왼쪽으로 (비공식적) 스팅 깊이를 1 이상 :

  • 주문 0 : 1 :: Int
  • 순서 1 : chr :: Int -> Char
  • 주문 2 : fix :: (a -> a) -> a,map :: (a -> b) -> [a] -> [b]
  • 순서 3 : ((A -> B) -> C) -> D
  • 주문 4 : (((A -> B) -> C) -> D) -> E

간단히 말해, 고품격 유형은 유형 수준의 고차 함수일뿐입니다.

  • 주문 0 : Int :: *
  • 순서 1 : Maybe :: * -> *
  • 순서 2 : Functor :: (* -> *) -> Constraint— 고급 : 단항 형식 생성자를 형식 클래스 제약 조건으로 변환

좋아, 스칼라에서 (* ⇒ *) ⇒ * 및 (* ⇒ *) ⇒ (* ⇒ *)에 대한 예는 무엇입니까? Landei의 Functor가 첫 번째 카테고리에 적합합니까 아니면 두 번째 카테고리에 적합합니까?
Lutz

1
@ lutz : 첫 번째 범주에 속합니다 : 형식 생성자에서 Functor적절한 유형 (잘, 특성, 그러나 동일한 아이디어) Functor[F[_]]을 생성 F합니다.
Jon Purdy 2016 년

1
@Jon : 매우 통찰력있는 게시물입니다. 감사합니다. 타입 변환기 (* => *) => (* => *)를 스칼라로 표현할 수 있습니까 ? 그렇지 않은 경우 다른 언어로?
Eugen Labun 2016 년

@JonPurdy 카레와의 비교 * ⇒ * ⇒ *는 매우 도움이됩니다. 감사!
Lifu Huang

(* ⇒ *) ⇒ (* ⇒ *)철자가 가능 (* ⇒ *) ⇒ * ⇒ *합니다. Scala와 같이 표현할 수 있습니다 Foo[F[_], T]. A (하스켈)과 같은 형태의이 종류 newtype Twice f a = Twice (f (f a))(예를 들어, Twice Maybe IntMaybe (Maybe Int), Twice [] Char[[Char]]) 또는 무료 모나드 같은 더 흥미로운 data Free f a = Pure a | Free (f (Free f a)).
Jon Purdy

37

나는 말할 것입니다 : 더 높은 종류 의 유형은 유형 생성자 위에 추상화 됩니다. 예를 들어

trait Functor [F[_]] {
   def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}

다음 Functor은 "고급 종류"( "고급의 일반인 "논문에 사용 된 )입니다. 이것은 List(적절한 유형에 대해서만 추상화되는) 것과 같은 구체적인 ( "1 차") 유형 생성자가 아닙니다. 모든 단항 ( "1 차") 유형 생성자 (로 표시됨)를 추상화 F[_]합니다.

또는 다른 말로 표현하자면 : Java에서는 명확하게 유형 생성자 (예 List<T>:)가 있지만 "상위 유형이 높은"유형은 없습니다. 예를 들어 Functor위에서 정의한 인터페이스를 작성할 수 없기 때문입니다. 적어도 직접적으로는 안됩니다 ).

"고차 (유형 생성자) 다형성"이라는 용어는 "고차 종류 유형"을 지원하는 시스템을 설명하는 데 사용됩니다.


이것은 내가 생각한 것이지만 "콘크리트 유형 생성자"가 이미 "더 높은 종류의 유형"인 Jon의 대답과 모순되는 것 같습니다.
Lutz

3
예. Jon의 대답에 따르면 (내가 이해하는 바와 같이) List<T>Java에서는 분명히 종류가 있기 때문에 단항 유형 생성자가 될 것 * -> *입니다. Jon의 대답에서 누락 된 것은 *더 높은 종류의 유형이라고하기 위해서는 "자바에서 와 같이 두 번째가 아닌 전체"에 대해 추상화 할 수 있어야한다는 것 입니다.
Landei

@Landai : 4.3 절의 일반 프로그래머위한 논문 Scala는 Iterable [A, Container [_]] 특성이 다른 유형의 vero690에서 Iterable [A, Container [_]]이 더 높은 유형 (Iterator 또는 Container가 확실하지는 않지만) 이라고 제안합니다 . 섹션 2.3.1은 Iterator 또는 Functor 특성과 유사한 (*-> *)-> * (상위 유형 생성자로 매개 변수화 된 유형 연산자)와 같은 상위 유형 유형 생성자 라는 용어를 사용합니다 .
Lutz

1
아마도 맞을지 모르지만 여기서 머리카락을 나누기 시작한 것 같습니다. 더 높은 종류의 유형에 관한 중요한 점은 유형 생성자가 관련 될뿐 아니라 (하나의 유형 생성자 다형성 순서), 우리는 해당 유형 생성자의 구체적인 유형 (고차 유형 생성자 다형성)을 추상화 할 수 있다는 것입니다. 우리는 제한없이 원하는 것을 추상화 할 수 있습니다 (유형 및 유형 생성자 포함).이 기능의 가능한 모든 버전의 이름을 지정하는 것은 덜 흥미 롭습니다. 그리고 그것은 내 뇌를 아프게합니다.
Landei

2
일반적으로 여기에서 정의와 참조를 구별하는 것이 중요합니다. 정의 def succ(x: Int) = x+1는 "값 생성자"를 소개합니다 (내가 의미하는 바에 대한 다른 답변 succ참조). 유추 Functor하여, (실제로 더 높은 종류의) 유형이 귀하의 답변에 정의되어 있습니다. 다시 말하지만, Functor[F[_]](무엇 F입니까? 무엇 _입니까? 범위에 속하지 않습니다! 불행히도, 실존 주의자에 대한 구문 설탕은 물을 F[_]짧게 만들어 여기에 물을 흐트립니다 F[T forSome {type T}])
Adriaan Moors

0

스칼라 REPL은 제공 :kind명령을하는

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

예를 들어

scala> trait Foo[A]
trait Foo

scala> trait Bar[F[_]]
trait Bar

scala> :kind -v Foo
Foo's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.

scala> :kind -v Foo[Int]
Foo[Int]'s kind is A
*
This is a proper type.

scala> :kind -v Bar
Bar's kind is X[F[A]]
(* -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.

scala> :kind -v Bar[Foo]
Bar[Foo]'s kind is A
*
This is a proper type.

(가) :help나는 그것이 전체가 여기에 가치 게시를 생각 때문에 명확한 정의를 제공합니다 (스칼라 2.13.2)

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

    -v      Displays verbose info.

"Kind" is a word used to classify types and type constructors
according to their level of abstractness.

Concrete, fully specified types such as `Int` and `Option[Int]`
are called "proper types" and denoted as `A` using Scala
notation, or with the `*` symbol.

    scala> :kind Option[Int]
    Option[Int]'s kind is A

In the above, `Option` is an example of a first-order type
constructor, which is denoted as `F[A]` using Scala notation, or
* -> * using the star notation. `:kind` also includes variance
information in its output, so if we ask for the kind of `Option`,
we actually see `F[+A]`:

    scala> :k -v Option
    Option's kind is F[+A]
    * -(+)-> *
    This is a type constructor: a 1st-order-kinded type.

When you have more complicated types, `:kind` can be used to find
out what you need to pass in.

    scala> trait ~>[-F1[_], +F2[_]] {}
    scala> :kind ~>
    ~>'s kind is X[-F1[A1],+F2[A2]]

This shows that `~>` accepts something of `F[A]` kind, such as
`List` or `Vector`. It's an example of a type constructor that
abstracts over type constructors, also known as a higher-order
type constructor or a higher-kinded type.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.