2013-03-02 6 views
4

이 경우의 :추론 ... 다음 ... 다른 이상한 행동 다음과 같은 나쁜 코드를 고려

내가 눈치
fun x = 
    if (null x) then 0 
    else (take 50 x) : (fun (drop 50 x)) 

, 나는 아무 문제없이 ghci에로드 할 수 있고, 그게 문제입니다.
이 기능을 평가하려고하면 프로그램에서 오류 만 검색합니다.

if ... then ... else 표현식의 기본 유추 규칙에 대해서는 두 개의 분기가 명시 적으로 다른 유형을 검색하므로 왜이 코드를로드 할 수 있습니까? 컴파일러가 왜이 코드가 잘못 작성되었다는 것을 알 수 없습니까?

참고 : 물론이 함수에 대해 올바른 형식 주석을 추가하면 예상대로 거부되지만 이해할 경우 형식 주석 없이도 거부해야합니다.

답변

16

오버로드 numeric literals. Haskell 숫자 리터럴은 타입 컨텍스트를 기반으로 정의 된 Num 클래스의 인스턴스입니다.

유추 유형은 설명 : 당신이 a 목록의 목록에 대한 민 클래스의 인스턴스가있는 경우

"로 읽고
Prelude> let f x = if null x then 0 else take 50 x : f (drop 50 x) 

Prelude> :t f 
f :: Num [[a]] => [a] -> [[a]] 

는,이 함수는리스트의 목록에 목록을합니다

목록의 목록에 대해 Num의 신화적인 인스턴스를 사용하므로 목록의 숫자에 대한 인스턴스를 제공하지 않고이 코드를 컴파일하려고하면 컴파일 오류가 발생합니다.

이 예제는 o 먼저 형식 서명을 적어 두는 것이 좋은 생각 인 이유를 설명합니다.

+3

Don의 답을 덧붙이면 : 이론적으로'[[a]]'에 대해'Num' 인스턴스를 정의 할 수 있습니다.이 경우 코드는 타입 체크를하고 Num Numeric 인스턴스를 사용하여 숫자 리터럴' 0 '이다. –

3

이것을 확인해 보겠습니다.

Prelude> let fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 
Prelude> :t fun 
fun :: Num [[a]] => [a] -> [[a]] 

당신은 컴파일러가 결과 유형에 대한 Num 클래스를 추론 볼 수 있듯이.