是否有一种将多态函数应用于Dynamic
类型值的理智方法?
例如,我的值为Dynamic
,我想将Just
应用于Dynamic
内的值。因此,如果值是toDyn True
构造的,我希望结果为toDyn (Just True)
。 <{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
返回所有内容