haskell types dynamic-typing

haskell - Cómo aplicar una función polimórfica a un valor dinámico



types dynamic-typing (1)

¿Existe una forma sensata de aplicar una función polimórfica a un valor de tipo Dynamic ?

Por ejemplo, tengo un valor de tipo Dynamic y quiero aplicar Just al valor dentro de la Dynamic . Entonces, si el valor fue construido por toDyn True , quiero que el resultado sea toDyn (Just True) . La cantidad de tipos diferentes que pueden ocurrir dentro de la Dynamic no está limitada.

(Tengo una solución cuando los tipos involucrados provienen de un universo cerrado, pero es desagradable).


Quizás este no sea el enfoque más sensato, pero podemos abusar de mi paquete de reflection para mentir sobre un 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)

Dado que ahora podemos echar un vistazo al TypeRep de nuestro argumento Dynamic y crear una instancia de nuestra función Dynamic manera adecuada.

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

Podría ser mucho más fácil si la base simplemente nos proporcionara algo como apD para nosotros, pero eso requiere un tipo de rango 2, y Typeable / Dynamic puede evitarlos, incluso si Data no lo hace.

Otra ruta sería simplemente explotar la implementación de Dynamic :

data Dynamic = Dynamic TypeRep Any

y unsafeCoerce a su propio tipo de datos Dynamic'' , haga lo que necesita hacer con el TypeRep en las TypeRep internas y, después de aplicar su función, unsafeCoerce todo lo anterior.