수색…


동의어 가족 유형

유형 동의어 패밀리는 유형 레벨 함수 일 뿐이며 매개 변수 유형을 결과 유형과 연관시킵니다. 이들은 3 개의 다른 다양성 들어온다.

폐쇄 형 - 동의어 계열

이것들은 통상적 인 값 - 레벨 하스켈 함수와 비슷하게 작동합니다 : 당신은 특정 타입을 다른 것들에 매핑하는 몇 가지 절을 지정합니다 :

{-# LANGUAGE TypeFamilies #-}
type family Vanquisher a where
    Vanquisher Rock = Paper
    Vanquisher Paper = Scissors
    Vanquisher Scissors = Rock

data Rock=Rock; data Paper=Paper; data Scissors=Scissors

열린 타입 - 동의어 계열

이것은 typeclass 인스턴스와 비슷하게 작동합니다. 다른 모듈에 더 많은 절을 추가 할 수 있습니다.

type family DoubledSize w

type instance DoubledSize Word16 = Word32
type instance DoubledSize Word32 = Word64
-- Other instances might appear in other modules, but two instances cannot overlap
-- in a way that would produce different results.

클래스 관련 유형 동의어

개방형 패밀리는 실제 클래스와 결합 될 수도 있습니다. 이것은 연관된 데이터 패밀리 와 마찬가지로 일부 클래스 메소드가 추가 헬퍼 객체를 필요로하고 이러한 헬퍼 객체 다른 인스턴스에 대해 다를 수 있지만 공유 될 수도있는 경우에 일반적으로 수행됩니다. 좋은 예가 VectorSpace 클래스입니다 .

class VectorSpace v where
  type Scalar v :: *
  (*^) :: Scalar v -> v -> v

instance VectorSpace Double where
  type Scalar Double = Double
  μ *^ n = μ * n

instance VectorSpace (Double,Double) where
  type Scalar (Double,Double) = Double
  μ *^ (n,m) = (μ*n, μ*m)
  
instance VectorSpace (Complex Double) where
  type Scalar (Complex Double) = Complex Double
  μ *^ n = μ*n

처음 두 인스턴스에서 Scalar 의 구현이 어떻게 동일한 지 확인하십시오. 이것은 연관된 데이터 패밀리에서는 가능하지 않습니다. 데이터 패밀리는 주사 형 이고, 형 동의어 패밀리는 그렇지 않습니다.

비 주입성은 위와 같은 가능성을 열어 주지만, 타입 유추를 더욱 어렵게 만듭니다. 예를 들어, 다음은 typecheck되지 않습니다 :

class Foo a where
  type Bar a :: *
  bar :: a -> Bar a
instance Foo Int where
  type Bar Int = String
  bar = show
instance Foo Double where
  type Bar Double = Bool
  bar = (>0)

main = putStrLn (bar 1)

이 경우, bar 대한 인수는 그 자체가 다형 Num Literal이므로, 컴파일러는 어떤 인스턴스를 사용할 지 알 수 없습니다. 그리고 타입 함수 Bar 는 "inverse direction"으로 해석 될 수 없습니다. 왜냐하면 그것은 injective 가 아니기 때문에 invertible이 아니기 때문입니다 ( Bar a = String 가진 하나 이상의 타입이있을 수 있습니다).


이 두 인스턴스 만 있으면 실제로 주입식이지만 컴파일러는 나중에 다른 인스턴스를 추가하지 않아 작동을 중단한다는 것을 알 수 없습니다.

데이터 유형 패밀리

데이터 패밀리는 유형 인수를 기반으로 다른 구현을 갖는 데이터 유형을 작성하는 데 사용될 수 있습니다.

독립형 데이터 제품군

{-# LANGUAGE TypeFamilies #-}
data family List a
data instance List Char = Nil | Cons Char (List Char)
data instance List () = UnitList Int

위의 선언에서 Nil :: List CharUnitList :: Int -> List ()

관련 데이터 제품군

데이터 패밀리는 typeclasses와 연관 될 수 있습니다. 이것은 일반적으로 일반적인 typeclass 메소드에 필요하지만 구체적인 인스턴스에 따라 다른 정보를 포함해야하는 "도우미 객체"가있는 유형에 유용합니다. 예를 들어, 목록의 색인 위치는 하나의 숫자 만 필요로하는 반면 트리에서는 각 노드의 경로를 나타내는 숫자가 필요합니다.

class Container f where
  data Location f
  get :: Location f -> f a -> Maybe a

instance Container [] where
  data Location [] = ListLoc Int
  get (ListLoc i) xs
    | i < length xs  = Just $ xs!!i
    | otherwise      = Nothing

instance Container Tree where
  data Location Tree = ThisNode | NodePath Int (Location Tree)
  get ThisNode (Node x _) = Just x
  get (NodePath i path) (Node _ sfo) = get path =<< get i sfo

분사율

유형 가족은 반드시 주입식 일 필요는 없습니다. 따라서 응용 프로그램에서 매개 변수를 유추 할 수 없습니다. 예를 들어, servant 에서 주어진 유형이 Server a 경우 유형 a 추론 할 수 없습니다. 이 문제를 해결하기 위해 Proxy 를 사용할 수 있습니다. 예를 들어, servant 에서 serve 함수는 유형 ... Proxy a -> Server a -> ... 우리는 추론 할 수 a 에서 Proxy a 하기 때문에 Proxy 에 의해 정의 된 data 단사이다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow