2011-12-28 11 views
1

하스켈이 타입 클래스에서 올바른 함수로 디스패치하는 방법에 대해 약간 혼란스러워합니다. 이것은 암묵적으로 행해지는 것입니까, 아니면 이것은 하스켈이 무언가의 유형을 추측하는 것과 관련이 있습니까? 예를 들어, 다음 사항을 고려하스켈 : 정확한 타입 지정을위한 디스패치 해결

instance Monad Parser where 
    return a = Parser (\ cs -> [(a, cs)]) 

내가 좋아하는 뭔가를 할 경우

return something >>= \x -> -- Returning a parser! 

바인드의 오른쪽을 사용하여 통화로 돌아가 하스켈 생각합니까? Parser를 다른 어떤 것과 반대로 호출하는 것을 어떻게 알 수 있습니까?

편집 :

좋아,이 사실은 나를 위해 더 많은 질문을 제기한다. 하스켈은 타입 선언을 해결함으로써 "반환"이 무엇인지 추측 할 수 있습니다. 그러나 완전히 모호한 진술의 경우는 어떨까요?

예를 들어 통역사를 열고 return 1을 입력하면 어떻게됩니까? 그러면 어떤 수익이 그 다음에 전화되는지 어떻게 알 수 있습니까?

+1

GHCi 문이 우선 몇 가지 * A *의 형태'IO의 A'의 것으로 간주됩니다 문자 "K"를 출력하고 실행되면 (그것을 실패하면'print it'을 시도합니다. * it *은 여러분이 입력 한 표현식입니다.)'return 1'은'(Num a) => IO a' 타입에 적합하기 때문에 실행됩니다; 'Num' 인스턴스는 하스켈의 기본 메커니즘 (Integer)으로 선택됩니다. – ehird

+0

'let x :: (Monad m, Num n) => m n; x = return 1' 확인해 보라.'x'는 * 다형성 값이다! 상황에 따라 유형이 'mn'모양을 가지며 제약 조건을 준수하는 값을 필요로하는 한 * 모든 상황에서 사용할 수 있습니다. 'm'은 '모나드'이고 'n'은 'Num'입니다. . 'x'는'[1.0] :: [Double]','Just 1 :: Maybe Int' ... 모든 종류의 것들이 될 수 있습니다! –

답변

4

맞습니다 - 하스켈은 반환 유형으로 발송할 수 있습니다. 사실 하스켈은 함수형 언어이기 때문에 "반환 유형"에 대한 엄격한 개념이 없습니다. 예를 들어, Int(Bool -> Int) -> String의 반환 유형입니까?

그래서 어떻게 될까요? 먼저 하스켈은 표현의 유형을 추론한다. 이 형태를 Ctx 컨텍스트이고 (Class1 vars1, Class2 vars2, ...) 형태를 갖는다

forall x1 x2 [...] . Ctx => t 

있다.

이제 대부분의 경우 (마찬가지로) 컨텍스트에서 발생하는 모든 유형 변수가 t 유형으로 나타납니다. 따라서 일단 변수가 구체화 된 유형으로 인스턴스화되면 오버로드 된 메소드를 해결할 수 있습니다.

구체적으로, 케이스에 하스켈 오른쪽 피연산자 일부 b의 형태 Parser b을 갖기 때문에 바인드 연산자 >>=이 유형

m a -> (a -> m b) -> m b. 

이 있는지 알고 상기 m 변수 정도로 return 타이핑 가지고 Parser 있어야 a -> Parser a.

어떤 경우에는 t에서 발생하지 않는 컨텍스트의 변수가있을 수 있습니다.

예.

show (read "blah") 

는 유형 String이 있지만 모두 ReadShow 클래스의 일부 인스턴스를 선택할 필요가 평가되어야한다.

이 경우 기본 메커니즘을 사용하여 해결되었거나 오류가보고됩니다. 후자의 경우 명시적인 서명을 제공하여 문제를 해결할 수 있습니다.

+2

'사실, 하스켈은 함수형 언어이기 때문에 "반환 유형"에 대한 엄격한 개념이 없습니다. "- 무엇? 함수형't -> u'를 생각해 봅시다.'u'는 T와 같이 "return type"에 들어 맞습니다.'f :: t -> u' 모든 함수의 반환 값 (또는 그 용어를 선호한다면 결과)은 다음과 같습니다. 'u'를 입력하십시오. 귀하의 예를 들면 :'(Bool -> Int) -> String'의'Int'는 실제로 반환 형식, 즉 고차 함수의 인수 인 함수의 반환 형식입니다. '문자열'은 상기 고차 함수의 리턴 타입이다. – delnan

+0

@delnan : 그것은 내부 함수의 리턴 타입이지만, 전체적으로 그것은 그것의 인자의 타입의 일부일뿐입니다. 또 다른 예 :'a'는'Foo a -> b'의 리턴 타입입니까? 당신은'Foo'가 그 대답에 어떻게 구현되어 있는지를 알아야합니다. 그리고 추상적 인 유형이라면? –

+0

'Foo a -> b '의 반환 유형은'b', 마침표입니다. 함수 인수에 대해 더 많이 알고 있으면 모든 재귀 호출을 수행하고 인수가 함수인지 리턴 유형이 무엇인지를 추가 할 수 있습니다.그러나 이것은 단지 추가 크레딧 일 뿐이며, 최상위 레벨 펑크 션의 결과 유형을 고려할 때는 관련이 없습니다. 고차 함수가 혼동하지 않도록하십시오. 각 함수는 정확히 하나의 인수 (유형)와 정확히 하나의 결과 (유형)를 갖습니다. 어느 것이 든 하나의 함수 일 수 있지만, 하스켈에게 함수는 단지 일반적인 값이다. – delnan

0

예를 들어, 인터프리터를 열어 1을 입력하면 어떻게됩니까?

당신이 시도 했습니까?

가있는 다음 통화로 돌아가 알 수 있습니까 어떻게

?

사실은 그렇지 않습니다. 그런 경우 올바른 작업을 수행 할 수 있도록 유형을 지정해야합니다. 예를 들어 : 하스켈 명령 "기본"을 참조하십시오

return 1 :: Maybe Int 
+0

나도 downvoting에 대한 이유를 말해 너무 좋을 거라고? – Ingo

1

은 "1을 반환"GHC에 의해 처리되고 조금씩 ghci.

이 편리

공식적으로 Haskell 98 Report here에 설명되어 있습니다. 당신이 무시할 수 서곡,의 "기본"선언은 다음과 같습니다

default (Integer,Double) 

"민"의 인스턴스 유형을 생산하는 무언가가 명시 적으로 요구하지 않도록 "기본"의 목적은 가장 일반적인 상황에서 주석을 입력하십시오. 위의 "기본"선언의 의미는 컴파일러가 먼저 정수 유형을 시도한 다음 Double 유형을 시도하는 것입니다. 올바른 컴파일을 허용하는 첫 번째 유형이 선택됩니다. 이 서면에 의해 완전히 해제 할 수 있습니다 : 당신은 컴파일러에 대한 자신의 힌트 목록을 만들 수 있습니다

default() 

또는하지만, 그렇지 않으면 서곡에 정의 또는 유일한 목록 유형의 표준 한계를 명시 적으로 컴파일러에 의해 허용 . 따라서 "기본"선언에 새 데이터 유형을 나열 할 수있는 권한이 보장되지 않습니다. GHC와

은 디폴트 규칙이 section 2.4.5 of the user manual에 있습니다. GHC는 항상 새로운 "Num"유형을 "기본값"으로 사용할 수 있습니다. 또한 언어 확장 "ExtendedDefaultRules"를 켜면 "default"선언은 "Show", "Eq"및 "Ord"인스턴스에 기본값을 제공 할 수 있습니다. 민에 대한 간단한 예 :

module Main where 

data K = K deriving (Show,Eq,Ord) 

instance Num K where fromInteger _ = K 

default (K) 

main = print 0 

ghci에서 실행이