2012-06-04 10 views
19

Polimorfik bir işlevi Dynamic türüne uygulamak için aklı başında bir yol var mı?Dinamik bir değere polimorfik işlev nasıl uygulanır

Örneğin, Dynamic türünde bir değere sahibim ve Dynamic'un içindeki değere Just uygulamak istiyorum. Yani, değer toDyn True tarafından oluşturulduysa, sonucun toDyn (Just True) olmasını istiyorum. Dynamic içinde meydana gelebilecek farklı türlerin sayısı sınırlandırılmaz.

(I türleri kapalı evren gelen içeriyordu bir çözüm var, ama hoş bir şey.)

+0

"Polytypeable" ve "polytypeable-utils" için kullanılabilir gibi görünüyor - yine de en iyi durumda, tam birleştirme uygulamak zorunda olsa da. – Carl

cevap

15

Bu belki sanest yaklaşım değildir, ama biz bir TypeRep hakkında yalan benim reflection paketini kötüye kullanabilir.

{-# 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) 

şimdi bizim Dynamic Tartışmanın TypeRep gözetleme ve uygun bizim Dynamic fonksiyonunu örneğini göz önüne alındığında. Bizim için apD, ama bu bir rütbe 2 tip gerektirir ve Typeable/Dynamic gibi base sadece verilen şey bunları önlemek için yönetiyorsanız

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())) 

O Data olmasa bile, çok daha kolay olabilir.

başka yolu Dynamic uygulanmasını istismar sadece olacaktır: Kendi Dynamic' veri türüne

data Dynamic = Dynamic TypeRep Any 

ve unsafeCoerce, sen içlerinde TypeRep ile yapmanız gerekenler yapın ve fonksiyonu uygulandıktan sonra , unsafeCoerce her şey geri döndü.

+2

'TypeRep' hakkında yalan söylemek zekice, bu yüzden bu cevabı kabul edeceğim ('' güvensizlik'i kullanarak '' '' '' '' dır, '' aklımızı '' olarak nitelendirmez. – augustss

+0

@augustss: Ahlaki fark nerede? –

+1

@AndreasRossberg Çok küçük. :) Ama eski biraz daha sağlam. Örneğin, 'Dinamik' uygulamasının değişmesi durumunda, 'TypeRep' ve 'Any' alanlarının yeri değişirse, öncekiler hala çöker. – augustss