2017-10-25 48 views
7

이유 ghci는 I가 패턴 매칭을 통해 제작이 함수 matchInt의 형태 서명에 equality type 제약을 나열 않는다 : 단순 데이터 생성자를 사용할 때패턴 일치로 생성 된 함수가 Eq 유형 제약 조건을 가지고 있지만 데이터 생성자를 사용하지 않는 이유는 무엇입니까?

이에
$ ghci 
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help 
Prelude> :{ 
Prelude| matchInt 1 = 3 
Prelude| matchInt _ = 4 
Prelude| :} 
Prelude> matchInt 1 
3 
Prelude> matchInt 22 
4 
Prelude> :t matchInt 
matchInt :: (Eq a, Num a, Num p) => a -> p 

는 어떠한 참가 형 제약이 없다. Z의

실제로
$ ghci 
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help 
Prelude> data Z = Y Int 
Prelude> :{ 
Prelude| matchDataInt (Y 1) = 3 
Prelude| matchDataInt _ = 4 
Prelude| :} 
Prelude> matchDataInt (Y 1) 
3 
Prelude> matchDataInt (Y 22) 
4 
Prelude> :t matchDataInt 
matchDataInt :: Num p => Z -> p 

인스턴스 비교할 수없는

Prelude> Y 22 == Y 33 
<interactive>:11:1: error: 
    • No instance for (Eq Z) arising from a use of ‘==’ 
    • In the expression: Y 22 == Y 33 
     In an equation for ‘it’: it = Y 22 == Y 33 

를 그래서 다시, 이유는 무엇입니까 matchInt 기능 목록 유형의 제약 조건으로 평등하지만 기능 matchDataInt?

question과 관련됩니다. 그러나 matchInt에 대한 동등성 테스트가 필요한 경우 matchDataInt은 왜 필요하지 않습니까? 그리고 여기에서 필자는 핵심 포인트에 도달했다 : matchIntmatchDataInt 모두 패턴 일치가 작동하도록 테스트해야합니까?

답변

10

을 정의 할 수 있습니다,하지만, 여기 Patern 일치는 환상입니다. 1은 데이터 생성자가 아닙니다. 숫자 리터럴에 과부하가 걸립니다. 1fromInteger #1과 같습니다. #1Integer 유형의 과부하가없는 litteral입니다 (표준 Haskell에서는 표현할 수 없음). 그런 것들과 실제로 일치하는 패턴을 만들 수는 없습니다.

그래서 컴파일러는 구문 패턴 일치 무엇을 작성할 수 있지만,이 표기법은 정말 가드를 나타냅니다 : matchInt의 유형이 명시 적으로 지정되지 않기 때문에

matchInt 1 = ... -- what is written 
matchInt x | x == fromInteger #1 = ... -- what it really means 

, 그것은 추정입니다. 그것은 함수이므로 형식은 a->b의 일부 상세 검색입니다. fromInteger을 호출하면 Num a이라는 제약 조건이 발생하고 ==을 호출하면 Eq a이라는 제약 조건이 발생하며 그 내용은 모두 a입니다. 우리는 기능을 명시 적으로 서명을 제공 OTOH 경우

은 우리가 유형을 추론 할 필요가 없습니다, 그러나 제약 조건을 만족하는 경우에만 확인

matchInt :: Int->Int 

을 말한다. IntEq Int과 을 모두 만족하므로 모든 사항이 정상입니다.

두 번째 예는 다음과 같습니다. 일치하는 형식은 Int으로 알려져 있으며 형식 서명이 명확하지 않기 때문에 Y Int 대체 형식 인 Z에서 유추 된 것으로 간주됩니다. 여기서 다시 Int에는 이미 필요한 모든 인스턴스가 있습니다.

7

는 특별히 Int에 일치 때문에 matchDataInt 함수는 Eq 제약 조건을 필요로하지 않으며, Int의 이미 Eq 인스턴스를 가지고있다.

귀하의 matchInt 기능은 매개 변수로 Int들하지 않는다 - 당신이 어떤지 그 번호를 비교할 수대로 한, 수의 어떤 종류를 취할 수 있습니다. 그렇기 때문에 유형이 (Eq a, Num a, Num p) => a -> p입니다. Int에는 이미 EqNum 인스턴스가 있으므로 Num p => Int -> p (a ~ Int) 유형을 지정할 수도 있습니다.

반면에 matchDataInt 함수는 Z을 인수로 사용하고 모든 ZInt을 포함합니다. 에 대한 패턴 일치는 IntEq 제약 조건을 갖지만 Int에만 이 해당합니다. 대신 할 수도 있습니다

data Z' a = Y' a 

matchDataNum :: (Eq a, Num a, Num p) => Z' a -> p 
matchDataNum (Y' 1) = 3 
matchDataNum _  = 4 

여기에서 Eq a 제약 조건을 제거 할 수 없습니다.


이 모든 것은 숫자 자체를 반환하지 않는 변형 함수로 약간 더 명확해질 수 있습니다.우리가

data Z = Y Int 
data Z' a = Y' a 

is1 1 = True 
is1 _ = False 

isY1 (Y 1) = True 
isY1 _  = False 

isY'1 (Y' 1) = True 
isY'1 _  = False 

이 경우 우리가 정의한 세 가지 기능은 유형

is1 :: (Eq a, Num a) => a -> Bool 
isY1 :: Z -> Bool 
isY'1 :: (Eq a, Num a) => Z' a -> Bool 

우리는 또한 패턴 일치를 기반으로 구문 적 matchInt

is1Int :: Int -> Bool 
is1Int 1 = True 
is1Int _ = False