2011-08-19 8 views
14

에서 "진정한"일반적인 기능은 I가 복합 데이터 유형을 가정하자. 예를 들어 -하스켈

f :: M o -> M o 
f (M (s,o)) = M (s++"!", o) 

그러나, f 내가 그것을 인 원하는만큼 정말 같은 일반적인 없습니다. 특히 표현식에 f을 사용하면 o 유형이 수정되므로 다른 유형의 o으로 f을 다시 사용할 수 없습니다. 예를 들어, 다음의 유형 체킹하지 않습니다 - 내가 인수로 f를 제공하는 대신 단순히 컴파일 후 F의 글로벌 정의를 사용하지 않는 경우, 놀랍게도 Couldn't match expected type 'Bool' with actual type '()'

-

p f = undefined where 
    m1 = M ("1",()) 
    m2 = M ("2", True) 
    m1' = f m1 
    m2' = f m2 

그것은 오류를 생성 잘 작동합니다! 즉 이것은 컴파일됩니다. -

p = undefined where 
    m1 = M ("1",()) 
    m2 = M ("2", True) 
    m1' = f m1 
    m2' = f m2 

특별한 이유가 있습니까? 어떻게하면이 문제를 해결할 수 있습니까? 즉 이 같은 표현식 내에서 변할 때도 모두 (M o)에 적용 할 수있는 함수 f을 정의 할 수 있습니까? 나는 실존 유형이 여기에 작용할 것으로 추측하고 있습니다. 그러나 나는 단지 그 방법을 이해할 수 없습니다.

+1

왜 M을 튜플로 만들겠습니까? 얼마나 못생긴가. – alternative

+1

기본적으로 "forall"은 무언가입니다. 이 텍스트를 볼 수 있습니다 : http://en.wikibooks.org/wiki/Haskell/Existentially_quantified_types – Nybble

+1

@monadic, 실제로는 실제 코드에서 직면했던 문제를 재현하는 최소한의 예입니다 (상당히 복잡합니다). –

답변

15

문제는 컴파일러가 p 유형을 올바르게 추론 할 수 없다는 것입니다. 당신이 언어 확장이 필요합니다, 그래서 이것은 순위 2 유형

p :: (forall o. M o -> M o) -> a 

: 당신은 그것을 유형 서명을 제공해야합니다

{-# LANGUAGE Rank2Types #-} 

또는

{-# LANGUAGE RankNTypes #-} 

읽기 여기에 대한 자세한 내용 : http://www.haskell.org/haskellwiki/Rank-N_types

+1

감사합니다! 해당 유형 서명을 추가하면 효과적입니다. 나는 그것이 forall 키워드와 관련이 있다고 생각했지만 RankN 유형에 대해서는 몰랐다. 내가 할 독서가있는 것 같아! –

5

특정 r이 있습니까? 이것에 대한 eason?

실제로 하나가 있습니다. 한 문장으로 말하면 : lambda 인수가 monomorphic해야 HM 시스템의 제한을 해제하면 형식 유추가 제대로 작동하지 않습니다.

Simon Peyton Jones는 HM을 확장하고 더 높은 순위의 다형성을 허용하는 유형 검사기를 고안했습니다. 그러나 이러한 경우에는 명시 적 유형 주석이 필요합니다. Sjoerds Answer를 참조하십시오.

2

p f 함수의 범위에있는 f은 최상위 함수 f과 동일하지 않습니다. p이 호출 될 때 어떤 함수가 인수로 주어집니다. p 형식 시그니처를 제공하지 않았기 때문에 컴파일러는 f의 사용법을 추론해야합니다. 처음 사용하면 p :: (M() -> M()) -> a을 의미하는 f :: M() -> M()을 의미합니다. 다른 사람이 말했듯이, 당신은 무엇을 하려는지 forall을 사용하여 p에 명시적인 서명을해야합니다.