2013-01-14 3 views
13

나는 극도로 무서운 기능인 unsafeCoerce를 사용하고있는 상황에 처해있다. 다행스럽게도 중요한 것은 아니지만이 기능을 안전하게 사용하는지, 아니면 다른 사람들이 알고있는이 특정 문제를 해결할 다른 방법이 있을지 궁금합니다. 주의 할이것은 unsafeCoerce를 안전하게 사용합니까?

data Token b = Token !Integer 

identical :: Token a -> Token b -> Bool 
identical (Token a) (Token b) = a == b 

data F a = forall b. F (Token b) (a -> b) 

retrieve :: Token b -> F a -> Maybe (a -> b) 
retrieve t (F t' f) = if identical t t' then Just (unsafeCoerce f) else Nothing 

두 가지 추가를,이 토큰은 내가 그들을 위해 정수의 공급이 고유한지 확인하는 데 사용하는 모나드 내에서 사용되는 것이 있습니다

내가 가진 코드는 다음과 같이이다 (즉, 나는 동일한 토큰을 두 번 만들지 않는다). 나는 또한 ST 모나드와 같은 방식으로, 정량화 된 그림자 타입 변수를 사용하여 (모듈에서 노출 된 메소드 만 사용된다고 가정 할 때) 토큰을 반환 할 방법이 없다는 것을 확인한다. F)를 형식 오류없이 모나드에서 제거합니다. 토큰 생성자도 공개하지 않습니다.

내가 볼 수있는 한, 안전하지 않은 상인의 ​​안전한 사용법이라고 생각한다. 나는 강요하고있는 가치가 실제로 나는 그것을 강요하고 있지만 잘못된 것일 수 있습니다. 나는 또한 Data.Typeable을 사용해 보았지만 멋지게 작동했다. 그러나 지금은 Typeable 제약을 피하려고 노력하고있다. 특히 gcast는 여러면에서 비슷한 방식으로 뭔가를하는 것으로 보이며, 토큰을 구별해야한다. 같은 타입의 다른 Fs.

도움/조언을 해주셔서 감사합니다.

+4

이것은'cast'를 구현하기 위해'unsafeCoerce'를 사용하는'Data.Typeable'과 매우 흡사합니다. –

+1

그것은 그와 매우 흡사합니다. 사실 iirc는 질문의 마지막 단락의 후반 부분에서 많은 것을 말했습니다. 어쨌든 고마워. – DarkOtter

+2

'cast'를 효과적으로 복사한다면'unsafeCoerce'의 사용법은 안전 합니다만 컴파일러가'typeOf' /'TypeRep'을 생성하지 못하게됩니다. 토큰에'Integer' 대신'TypeRep'을 사용하는 것을 고려할 수 있습니다. –

답변

9

그것은 본질적으로 안전하지 :

oops :: F Bool 
oops = F (Token 12) not 

bad :: Token Int 
bad = Token 12 

*Token> maybe 3 ($ True) $ retrieve bad oops 
1077477808 

F a가 존재 적 정량화 유형, 당신은 b이 들어갔다 유형을 알 수 없습니다. identicalToken에 대한 유형 매개 변수에 대해 신경 쓰지 않으므로 F a에 들어간 값과의 첫 번째 인수와 관련이 있는지 확인 할 수 없습니다.

두 가지 추가 보호 기능이 주목하는 여부,이 토큰 내가하지 않는 즉, (그들을 위해 정수의 공급이 고유한지 내가 확인하는 데 사용하는 모나드 내에서 사용되는 것이있다 같은 토큰을 두 번). 나는 또한 ST 모나드와 같은 방식으로, 정량화 된 그림자 타입 변수를 사용하여 (모듈에서 노출 된 메소드 만 사용된다고 가정 할 때) 토큰을 반환 할 방법이 없다는 것을 확인한다. F)를 형식 오류없이 모나드에서 제거합니다. 토큰 생성자도 공개하지 않습니다.

은 실제로 안전하기에 충분히 강하기 때문에 보지 않고 말할 수 없습니다. 실제로 Token을 계산 외부에서 생성 할 수없고 TokenInteger 값이 유형 매개 변수를 고유하게 특성화하는 경우 안전합니다.

14

사용자는 Data.Dynamic의 스타일을 광범위하게 따르는 제한된 형식의 동적 입력을 구현했습니다. 즉, (불투명 한) 값을 해당 유형의 증거와 비교하여 Paring합니다. 런타임시 데이터와 함께 제공된 증거를 기반으로 안전하지 않은 강제 변환을 수행 할 수 있습니다.

fromDyn (Dynamic t v) def 
    | typeOf def == t = unsafeCoerce v 
    | otherwise  = def 

이것은 canoncial 접근 방식은 다시가는, 오랜 역사를 가진입니다 :

Mart'ın 아 바디, 루카 카르 델리, 벤자민 피어스, 그리고 고든 플롯 킨. 정적으로 입력 된 언어로 동적 입력. ACM 프로그래밍 언어 및 시스템의 트랜잭션, 13 (2) : 237-268, 1991 년 4 월

접근의 안전은 런타임 타입 토큰의 위조 불가에 의존합니다. 귀하의 경우에는 누구든지 두 가지 유형을 동일한 토큰을 만들 수 있습니다. 유형과 토큰 간의 1-1 매핑을 보장하고 악의적 인 사용자가 잘못된 토큰을 만들 수 없도록해야합니다. GHC의 경우 Typeable 인스턴스 (및 모듈 추상화)를 신뢰합니다.