ポリモーフィック関数を型の値に適用する正しい方法はありますDynamicか?
たとえば、typeの値があり、内の値Dynamicに適用したいとします。したがって、値がによって作成された場合、結果はになります。内部で発生する可能性のあるさまざまなタイプの数に制限はありません。JustDynamictoDyn TruetoDyn (Just True)Dynamic
(関係するタイプが閉じた宇宙からのものである場合、私には解決策がありますが、それは不快です。)
ポリモーフィック関数を型の値に適用する正しい方法はありますDynamicか?
たとえば、typeの値があり、内の値Dynamicに適用したいとします。したがって、値がによって作成された場合、結果はになります。内部で発生する可能性のあるさまざまなタイプの数に制限はありません。JustDynamictoDyn TruetoDyn (Just True)Dynamic
(関係するタイプが閉じた宇宙からのものである場合、私には解決策がありますが、それは不快です。)
これはおそらく最も健全なアプローチではありませんが、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'必要なことを行い、関数を適用した後、すべてを元に戻します。TypeRepunsafeCoerce