2014-07-13 2 views
15

올바른 버전으로 내 코드를 반복, 나는 다음과 호기심을 가로 질러 온 반면 :하자 - 이름 바꾸기 기능 구분 코드를

{-# LANGUAGE RankNTypes #-} 

module Foo where 

import Data.Vector.Generic.Mutable as M 
import Control.Monad.Primitive 

-- an in-place vector function with dimension 
data DimFun v m r = 
    DimFun Int (v (PrimState m) r -> m()) 

eval :: (PrimMonad m, MVector v r) => DimFun v m r -> v (PrimState m) r -> m() 
eval = error "" 

iterateFunc :: (PrimMonad m, MVector v r) 
      => (forall v' . (MVector v' r) => DimFun v' m r) -> DimFun v m r 
iterateFunc = error "" 

f :: (PrimMonad m, MVector v r) 
     => DimFun v m r 
f = error "" 

iteratedF :: (MVector v r, PrimMonad m) 
      => v (PrimState m) r -> m() 
iteratedF y = 
    let f' = f 
    in eval (iterateFunc f') y 

이 코드는 컴파일되지 않습니다 :

Testing/Foo.hs:87:14: 
    Could not deduce (MVector v0 r) arising from a use of ‘f’ 
    from the context (MVector v r, PrimMonad m) 
     bound by the type signature for 
       iteratedF :: (MVector v r, PrimMonad m) => 
           v (PrimState m) r -> m() 
     at Testing/Foo.hs:(84,14)-(85,39) 
    The type variable ‘v0’ is ambiguous 
    Relevant bindings include 
     f' :: DimFun v0 m r (bound at Testing/Foo.hs:87:9) 
     y :: v (PrimState m) r (bound at Testing/Foo.hs:86:11) 
     iteratedF :: v (PrimState m) r -> m() 
     (bound at Testing/Foo.hs:86:1) 
    In the expression: f 
    In an equation for ‘f'’: f' = f 
    In the expression: let f' = f in eval (iterateFunc f') y 

Testing/Foo.hs:88:26: 
    Couldn't match type ‘v0’ with ‘v'’ 
     because type variable ‘v'’ would escape its scope 
    This (rigid, skolem) type variable is bound by 
     a type expected by the context: MVector v' r => DimFun v' m r 
     at Testing/Foo.hs:88:14-27 
    Expected type: DimFun v' m r 
     Actual type: DimFun v0 m r 
    Relevant bindings include 
     f' :: DimFun v0 m r (bound at Testing/Foo.hs:87:9) 
    In the first argument of ‘iterateFunc’, namely ‘f'’ 
    In the first argument of ‘eval’, namely ‘(iterateFunc f')’ 
Failed, modules loaded: none. 

을하지만, 내가 변경하는 경우 iteratedF에서

iteratedF y = eval (iterateFunc f) y 

의 정의는 GHC 7.8.2로 컴파일됩니다. 이 질문은 이상한 모양의 서명이나 데이터 유형에 관한 것이 아니라 단순히 다음과 같습니다. f에서 f'으로 이름을 바꾼 이유는 무엇입니까? 이것은 저에게 버그가되어야하는 것 같습니다.

답변

7

을하지 이름 바꾸기를 추가,하지만 새로운 변수에 바인딩. iterateFunc은 Rank-2이기 때문에 다형 함수 인수 함수가 필요합니다. 물론 fv에서 다형성을 가지므로 사용할 수 있습니다. 그러나 f' = f을 쓸 때 f'이 어떤 종류인지 명확하지 않습니다. f과 동일한 다형성 유형 또는 일부 유형의 변수와 다른 유형의 변수에 따라 컴파일러가 아직 추론하지 않은 iteratedF의 변수에 따라 다를 수 있습니다.

컴파일러의 기본값은 모노 형태 옵션입니다. chi가 여기에 monomorphism 제한의 잘못이 있다고 말하면 코드를 컴파일하면 실제로 컴파일됩니다.

여전히 동일한 문제는 RankNTypes 코드의 단일 동색 제한없이 나타날 수 있습니다. 완전히 피할 수는 없습니다. 신뢰할 수있는 유일한 수정 프로그램은 로컬 서명이며 대개 ScopedTypeVariables이 필요합니다.

+2

다음은 무시 무시한 단일 변체 제한의 또 다른 경우이다. – crockeea

+4

나는 이름 바꾸기가 순수 하스켈 98에서 문제를 일으킬 수 없다고 생각하지 않는다.''f f = show in f 1 ++ f True'를 고려하자. –

12

모노 형태 제한을 비활성화하면 코드를 컴파일 할 수 있습니다. 따라서 파일 시작 부분에

{-# LANGUAGE NoMonomorphismRestriction #-} 

을 추가하십시오.

유형 오류가 발생한 이유는 정의

let f' = f 

함수 패턴을 사용하지 않고 (예 f' x y = ...)를 상기 단사 사상 제한이있는 발 차기 및 iterateFunc 다형성을 요구하면서 힘 f'는 단형 수 있도록 기능.

는 다른 방법으로, 문제는 물론이고 유형 약어

let f' :: (PrimMonad m, MVector v r) => DimFun v m r 
    f' = f 
+1

이상한 점은 ghc-7.8에서'NoMono ... '플래그가 필요하다는 것입니다 ... 나는 그것이 단조 제한을 완전히 해제했다고 생각했지만 분명히 최상위 레벨이나 다른 것에서 만 작동합니다. – leftaroundabout

+7

@leftaroundabout 나는 단지 GHCi 일 뿐이라고 생각한다. – bennofs