2011-09-10 23 views
8

Lo maravilloso de Haskell. El tipo de una función casi dicta su implementación. Ese es el caso de éste, pero ... mi cerebro no está envolviendo alrededor de la función anidada cosa aquí:Cómo implementar esta función en Haskell

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 

La única pregunta es cómo manejar el control de errores en la llamada fromDynamic que será requerida, pero ... puedo lidiar con eso una vez que tenga el resto resuelto. Supongo que tendrá que haber algo como lo siguiente en alguna parte. Pero parece que no puedo descifrar la envoltura lambda.

case fromDynamic x of 
    Just x -> f x 
    Nothing -> undefined -- TODO 
+1

Guau, ni siquiera sabía que Haskell tenía soporte de tipo dinámico, y menos aún que estaba [disponible en la base] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/ Data-Dynamic.html). Aprenda algo nuevo cada día. –

+0

@Joey IIRC incluso hay una biblioteca para escribir código de estilo imperativo con operadores de asignación fácil, pero olvidé dónde. Creo que fue mencionado una vez en Planet Haskell. – fuz

Respuesta

10

Creo que quieres toDyn, no fromDynamic. Así que vamos a hacer esto lentamente:

mkDyn :: Typeable a => 
     ((a -> IO()) -> IO()) 
     -> (Dynamic -> IO()) 
     -> IO() 
mkDyn k f = ... 

Nuestro tipo de retorno debe ser IO() y podemos conseguir que sea llamando o kf. Llamar a f no nos ayuda mucho, porque de alguna manera materializamos un Dynamic, pero no podemos hacer eso (sensatamente) desde k. Entonces queremos llamar al k. k necesita otra función como su argumento, por lo que vamos a empezar así:

mkDyn k f = k (\a -> ...) 

Así que el argumento de la función es Typeable a => a -> IO(). No tenemos una función de ese tipo, pero tenemos una función del tipo Dynamic -> IO(). Debido a la restricción Typeable podemos utilizar toDyn a dirigir nuestra a en Dynamic y obtener:.

mkDyn k f = k (\a -> f (toDyn a)) 

Existen implementaciones más simples (por ejemplo, return() o k (\a -> return()), pero éste parece tener sentido

+0

mkDyn k f = k $ f. toDyn – rampion

+3

@rampion ¡Dos pueden jugar ese juego! 'mkDyn = (. (. toDyn))'. –

+2

Tiendo a preferir las versiones puntiagudas. Solo uso estilo sin puntos si las cosas son realmente solo una tubería simple. Cualquier cosa (incluso ligeramente) más complicada y lamentaría la próxima vez que leyera el código. – nominolo

4

hice trampa y se utiliza la Djinn program

primera vez que generalizó el tipo determinado:.

f :: (a -> c) 
    -> ((a -> b) -> b) 
    -> ((c -> b) -> b) 

La (a -> c) representa la función toDyn function, y c representa Dynamic. b representa IO().

de Djinn resultado fue sorprendentemente simple:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b) 
f a b c = b (\ d -> c (a d)) 

lo que es más específico (reemplazando el (a -> c) con la función toDyn), obtenemos:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 
mkDyn b c = b (\ d -> c (toDyn d)) 

que coincide nominolo's answer.

+1

¿Esto prueba que nominolo es un djinn? – Landei

Cuestiones relacionadas