如何将多态函数应用于动态值

时间:2012-06-04 23:18:06

标签: haskell types dynamic-typing

是否有一种将多态函数应用于Dynamic类型值的理智方法?

例如,我的值为Dynamic,我想将Just应用于Dynamic内的值。因此,如果值是toDyn True构造的,我希望结果为toDyn (Just True)。 <{1}}内可能出现的不同类型的数量不受限制。

(当涉及的类型来自封闭的宇宙时,我有一个解决方案,但这是令人不愉快的。)

1 个答案:

答案 0 :(得分:15)

这可能不是最认真的方法,但我们可以滥用我的reflection包来讨论TypeRep。

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

鉴于我们现在可以查看TypeRep参数的Dynamic并适当地实例化我们的Dynamic函数。

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

如果base为我们提供了类似apD的内容,但这需要排名为2的类型,Typeable / Dynamic设法避免他们,即使Data没有。

另一条路径就是利用Dynamic的实现:

data Dynamic = Dynamic TypeRep Any

unsafeCoerce到您自己的Dynamic'数据类型,执行您需要对内部TypeRep执行的操作,并在应用您的函数后,unsafeCoerce返回所有内容