2014-02-27 2 views
1

하스켈의 형식 시스템을 이해하려고합니다. 그리고 난 다음에 따라 온 :하스켈의 쌍을위한 형식

*Main> :t ("Hello", 4) 
("Hello", 4) :: Num t => ([Char], t) 

*Main> :t ("Hello", 'a') 
("Hello", 'a') :: ([Char], Char) 

*Main> :t ("Hello", True) 
("Hello", True) :: ([Char], Bool) 

는 왜 다른 사람처럼 표시 ("Hello", 4)의 유형입니다. 나는 그것이 ("Hello", 4) :: ([Char], Num)

내가 전에 =>을 본 것을 기대했을 것입니다. 내가 궁금해하는 점은 그것이 왜이 차이를 만드는가?

답변

11

Num은 유형이 아닙니다. typeclass이고 Num t => someTypetNum typeclass의 인스턴스 인 임의의 유형이라는 것을 의미합니다. Java/C# 용어를 빌리려면 Num을 인터페이스로 생각하고 Num t => ttNum 인터페이스를 구현해야한다는 제약 조건을 가진 제네릭 유형입니다.

일반적으로 => 화살표의 왼쪽과 오른쪽의 유형 본문에서 typeclass 제약 조건을 찾습니다. 예를 들어 (Num a, Num b) => (a, b)과 같이 여러 개의 클래스 제약 조건을 가질 수 있습니다.이 제약 조건은 두 개의 임의 숫자 형식으로 된 튜플 유형을 나타냅니다. 우리는 또한 0 클래스 제약을 가질 수 있으며,이 경우 =>은 생략됩니다.

하스켈에서 숫자 리터럴은 Num의 인스턴스 인 모든 유형을 나타낼 수 있습니다. 리터럴 4은 부동 소수점 또는 정수를 나타낼 수도 있고, 더 복잡한 이질적인 인스턴스를 정의하는 경우 함수를 나타낼 수도 있습니다.

2

Num은 typeclass입니다. Typeclasses는 OO 인터페이스와 비슷하지만 (실제로는 그렇지 않습니다). 다른 타입들은 다형성을 허용하면서 typeclass의 기능을 구현합니다.

예를 들어,

class Eq a where 
    (==) :: a -> a -> Bool 
    (/=) :: a -> a -> Bool 

이것은 당신이 isMember :: (Eq a) => a -> [a] -> Bool 같은 기능을 쓸 수 있다는 것을 의미한다 (당신이 :info Eq과 ghci이를 얻을 수 있습니다)로 정의되는 표준 Eq 클래스가있다. 이 함수는 Eq을 구현하고 (인스턴스가 있음) 동일한 유형의 목록을 구현하는 유형 a을 취해 부울을 반환합니다. 이 제네릭 형식의 서명은 다시 원래의 질문에, 당신은

elem 'c' "abcd" 
elem 4 [1,2,3] 

을 할 수 있으며 컴파일되지만 지금

elem 'c' [1,2,3] 

을 할 수 없다는 것을 의미한다. ghci에 숫자를 입력하면 해당 숫자를 가능한 가장 일반적인 유형으로 지정하려고 시도합니다. 5Int인지 또는 Integer인지, 아니면 Double인지는 알 수 없습니다. 그래서, 리터럴.

다른 식을 당신에게 더 구체적인 유형을 제공 할 것입니다.)이 Num typeclass를 구현하는 것보다이 일이 어떤 종류의 t을 가질 수있다 "를 의미 유형 (Num t) => t을 가지고 예를 들어, 5 `div` 3div이기 때문에, (Integral a) => a을 입력있다 Integral 클래스의 메서드

안경에 대해 더 자세히 알고 싶으면 this이 좋은 링크입니다.

2

숫자 리터럴은 특별한 경우이며 4은 예를 들어. Int 또는 Integer으로 해석되며 컴파일러는이 선택을하지 않지만 공통된 타입 클래스 인 Num의 형태로 "최소 공통 분모"를 취합니다 (다른 답변은 이미 설명했듯이).

이 시점에서 더 구체적인 경우 내가 만들려고 추가 점은, 이상한 것들이 사라집니다 :

-- specify Int explicitly 
*Main> :t ("Hello", 4 :: Int) 
("Hello", 4 :: Int) :: ([Char], Int) 

-- specify Integer explicitly 
*Main> :t ("Hello", 4 :: Integer) 
("Hello", 4 :: Integer) :: ([Char], Integer) 

-- use an Int result from an expression 
*Main> :t ("Hello", length [1,2,3]) 
("Hello", length [1,2,3]) :: ([Char], Int)