2012-04-21 35 views
8

¿Es posible escribir una función isFunc :: a -> Bool para determinar si un valor arbitrario es una función (de cualquier tipo) de tal manera queDeterminar si un valor es una función en Haskell

foo :: Int -> Int 
bar :: Char -> Char -> Char  

> isFunc foo 
True 
> isFunc bar 
True 
> isFunc 3 
False 
> isFunc 'a' 
False 

estoy usando lo que Data.Dynamic no puede determinar el tipo de antemano.

+3

'isFunc' no es una pregunta bien formado para preguntar en presencia de polimorfismo. Tengo una cosa de tipo 'a'; ¿es una función o no? La respuesta es indeterminada hasta que haya convertido 'a' en un tipo monomórfico, ya que hasta entonces podía elegir, por ejemplo,' a ~ Int' o 'a ~ Int -> Int'. Tu ejemplo 'isFunc 3' tiene exactamente este problema, y ​​probablemente ni siquiera lo notaste; ¿Cómo sabes que '3' no es una función? –

Respuesta

10

Parametricity dice no. Las únicas funciones del tipo

a -> Bool 

son funciones constantes.

Sin embargo, con un poco de polimorfismo ad hoc y un poco más cara dura, se puede hacer esto:

{-# LANGUAGE OverlappingInstances, FlexibleInstances #-} 

class Sick x where 
    isFunc :: x -> Bool 

instance Sick (a -> b) where 
    isFunc _ = True 

instance Sick x where 
    isFunc _ = False 

y entonces parece que tiene

*Sick> isFunc 3 
False 
*Sick> isFunc id 
True 

pero lo hace parecer como una cosa peculiar que hacer ¿Para qué sirve el resultado Bool?

+0

Estoy mapeando sobre una lista de valores tipeados dinámicamente y aplicando x a aquellos que son funciones. – jhibberd

+1

No estoy seguro de que este enfoque realmente funcione para ese problema, o, francamente, que cualquier enfoque funcionará para ese problema, en Haskell. Las instancias de clase de pila en Haskell siempre se resuelven en tiempo de compilación, no en tiempo de ejecución, y la situación que describes parece requerir resolución en tiempo de ejecución. –

11

Lo que está pidiendo y lo que necesita hacer con Data.Dynamic parece ser cosas diferentes. Necesita saber el tipo exacto de valor antes de extraerlo con fromDyn/fromDynamic. Para determinar si Dynamic contiene un valor de la función es necesario analizar TypeRep:

isFuncDynamic x = typeRepTyCon (dynTypeRep x) == typeRepTyCon (typeOf2 id) 

(Perdóname si esto no es la implementación más concisa.)

+0

Gracias. Esta función (aunque construida manualmente) es justo lo que estaba buscando. – jhibberd

Cuestiones relacionadas