Pregunta

¿Es posible escribir una función? arity :: a -> Integer para determinar la aridad de las funciones arbitrarias, de modo que

> arity map
2
> arity foldr
3
> arity id
1
> arity "hello"
0

?

¿Fue útil?

Solución

Es fácil con OverlappingInstances:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Arity f where
  arity :: f -> Int

instance Arity x where
  arity _ = 0

instance Arity f => Arity ((->) a f) where
  arity f = 1 + arity (f undefined) 

Actual Encontrado problema. Debe especificar el tipo no polimórfico para las funciones polimórficas:

arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)

No sé cómo resolver esto todavía.

Actual2 Como Sjoerd Visscher comentó a continuación "Debe especificar un tipo no polimórfico, ya que la respuesta depende de qué tipo elija".

Otros consejos

Sí, se puede hacer muy, muy fácilmente:

arity :: (a -> b) -> Int
arity = const 1

Justificación: si es una función, puede aplicarla a exactamente 1 argumento. Tenga en cuenta que la sintaxis de Haskell hace imposible aplicar a 0, 2 o más argumentos como f a b realmente es (f a) b, es decir, no f applied to a and b, pero (f applied to a) applied to b. El resultado puede, por supuesto, ser otra función que se pueda aplicar nuevamente, y así sucesivamente.

Suena estúpido, pero no es más que la verdad.

Si id tiene arity 1, no debería id x ¿Tienes arity 0? Pero, por ejemplo, id map es idéntico a map, que tendría arity 2 en tu ejemplo.

¿Tiene las siguientes funciones la misma aridad?

f1 = (+)
f2 = (\x y -> x + y)
f3 x y = x + y

Creo que tu noción de "aridad" no está bien definida ...

En Haskell, cada "función" toma exactamente un argumento. Lo que parece una función de "múltiple argumento" es en realidad una función que toma un argumento y devuelve otra función que toma el resto de los argumentos. Entonces, en ese sentido, todas las funciones tienen aridad 1.

No es posible con Haskell estándar. Es posible usar las incoherentinstancias o una extensión similar.

Pero, ¿por qué quieres hacer esto? No puede preguntarle a una función cuántos argumentos espera y luego usar este conocimiento para darle precisamente ese número de argumentos. (A menos que esté utilizando la plantilla Haskell, en cuyo caso, sí, espero que sea posible en el momento de la compilación. ¿Está utilizando la plantilla Haskell?)

¿Cuál es tu problema real que estás tratando de resolver?

Qué tal esto:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top