2012-06-04 5 views
19

Dynamic 값에 다형 함수를 적용하는 정상적인 방법이 있습니까?다형 함수를 동적 값에 적용하는 방법

예를 들어 Dynamic 유형의 값이 있으며 Dynamic 내부의 값에 Just을 적용하고 싶습니다. 그래서 값이 toDyn True에 의해 생성 된 경우 결과는 toDyn (Just True)이 되길 원합니다. Dynamic 안에 발생할 수있는 여러 유형의 수는 제한되지 않습니다.

는 (나는 종류가 닫힌 우주에서 온 관련된 솔루션을 가지고 있지만, 그것은 불쾌한입니다.)

+0

'polytypeable'과'polytypeable-utils'가이 용도로 사용될 수 있습니다 -하지만 최악의 경우에는 완전한 통합을 구현해야합니다. – Carl

답변

15

이것은 아마도 sanest 접근 아니지만, 우리는 TypeRep 거짓말 내 reflection 패키지를 남용 할 수 있습니다.

{-# LANGUAGE Rank2Types, FlexibleContexts, ScopedTypeVariables #-} 
import Data.Dynamic 
import Data.Proxy 
import Data.Reflection 
import GHC.Prim (Any) 
import Unsafe.Coerce 

newtype WithRep s a = WithRep { withRep :: a } 

instance Reifies s TypeRep => Typeable (WithRep s a) where 
    typeOf s = reflect (Proxy :: Proxy s) 

우리는 지금 우리의 Dynamic 인수의 TypeRep 훔쳐 적절하게 우리의 Dynamic 기능을 인스턴스화 할 수 있음을 감안할 때. 우리 apD,하지만 그 순위 2 유형을 필요로하고, Typeable/Dynamic 같은 base 단지 공급 뭔가를 방지하기 위해 관리하는 경우

apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic 
apD f a = dynApp df a 
    where t = dynTypeRep a 
     df = reify (mkFunTy t (typeOf1 (undefined :: f()) `mkAppTy` t)) $ 
        \(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f())) 

그것은 Data하지 않는 경우에도, 훨씬 더 쉽게 될 수 있습니다.

또 다른 경로가 Dynamic의 구현 이용 만하는 것입니다 : 당신의 자신의 Dynamic' 데이터 유형에

data Dynamic = Dynamic TypeRep Any 

unsafeCoerce, 당신은 내부에있는 TypeRep와 함께 할 필요가 무엇을하고 기능을 적용한 후 , unsafeCoerce 모든 것.

+2

'TypeRep'에 관한 거짓말은 독창적 인 것이므로이 대답을 받아 들일 것입니다. ('unsafeCoerce'를 사용하여'Dynamic' 내부의 엿보기와 찌르기는 제정신이 아닙니다.) – augustss

+0

@augustss : 도덕적 인 차이점은 어디에 있습니까? –

+1

@AndreasRossberg 아주 작습니다. :)하지만 전은 다소 강하다. 예를 들어, 'Dynamic'구현이 변경되어 TypeRep 및 Any 필드가 변경되면 전자는 여전히 작동하지만 후자는 충돌합니다. – augustss

관련 문제