tuplas sobre recursivos opciones multiplos multiplicar listas infinitas hacer funciones ejercicios como ciclos basico haskell recursion types functional-programming

sobre - multiplicar haskell



Aprendizaje de mapas, pliegues, bucles y recursiones de Haskell (4)

No busco simplemente una respuesta, sino una explicación más detallada.

En el lado izquierdo de = se usa sum como una función aplicada a x . El compilador no conoce el tipo de x , por lo que el compilador usa la variable de tipo a para "el tipo de x ". En este punto, el compilador tampoco conoce el tipo de resultado de la función sum , por lo que elige otra variable de tipo, este tipo t , para representar el tipo de resultado. Ahora, en el lado izquierdo, el compilador piensa que el tipo de x es a -> t (función que acepta a y devuelve t ).

En el lado derecho de =, agrega x y sum . En Haskell se pueden agregar todos los tipos de números, pero solo puede agregar dos si tienen el mismo tipo. Entonces, aquí el compilador supone que la sum tiene el mismo tipo que x , es decir, escriba a .

Pero en Haskell un identificador tiene un tipo, tal vez un tipo complicado, pero de todos modos un tipo. Esto incluye la sum , cuyo tipo debe ser el mismo en ambos lados del signo `, por lo que el compilador intenta resolver la ecuación

a = a -> t

No hay valores para a y t que resuelvan esta ecuación. Simplemente no se puede hacer. No hay a tal que a sea ​​igual a una función que se acepta a sí misma como argumento. Así surge el mensaje de error

cannot construct the infinite type: a = a -> t

Incluso con toda la explicación, no es un gran mensaje de error, ¿verdad?

Bienvenido a Haskell :-)

PD. Puede que te guste probar "Helium, para aprender Haskell", que ofrece mensajes de error mucho más agradables para principiantes.

Acabo de sumergirme en el mundo de Haskell como parte de mi viaje de programación esclarecedora (pasando de procedimental a OOP a concurrente y ahora funcional).

He estado probando un Evaluador de Haskell en línea.

Sin embargo, ahora estoy atascado en un problema:

Cree una función simple que proporcione la suma total de una matriz de números.

En un lenguaje de procedimiento, esto para mí es bastante fácil (usando recursividad) (c #):

private int sum(ArrayList x, int i) { if (!(x.Count < i + 1)) { int t = 0; t = x.Item(i); t = sum(x, i + 1) + t; return t; } }

Todo muy bien, pero mi intento fallido en Haskell fue así:

let sum x = x+sum in map sum [1..10]

esto resultó en el siguiente error (desde ese sitio web mencionado anteriormente):

Occurs check: cannot construct the infinite type: a = a -> t

Tenga en cuenta que solo he usado Haskell durante los últimos 30 minutos.

No busco simplemente una respuesta, sino una explicación más detallada.


Necesita leer un buen tutorial, hay una serie de grandes malentendidos.

Primero voy a suponer que quieres decir listas y no matrices. Las matrices existen en Haskell, pero no son algo que te encuentres en el nivel de principiante. (Sin mencionar que está usando [1..10] que es una lista de los números del 1 al 10).

La función que desea está integrada y llamada sum, por lo que tendremos que llamar a nuestra otra cosa, new_sum:

new_sum [] = 0 new_sum (h:t) = h + (sum t)


Veamos la primera parte de esto:

let sum x = x+sum

¿Cuál sería el tipo de suma en este caso? Toma un número y devuelve una función que toma un número que devuelve una función que toma un número, etc. si lo hubiera escrito, deje suma x = + x tendría una función que toma un número y devuelve la función + x. y let sum = + devolvería una función que toma dos enteros y los agrega.

así que ahora veamos la segunda parte. en la suma del mapa [1..10] el mapa toma una función de un argumento y lo aplica a cada elemento de la lista. No hay espacio para encajar un acumulador allí, así que veamos otras funciones de lista en particular foldl, foldr. ambos toman una función de dos argumentos, una lista y un valor inicial. La diferencia entre foldl y foldr está en el lado en el que comienzan. Quedando así 1 + 2 + 3 etc. y r siendo 10 + 9 + 8, etc.

let sum = (+) en foldl sum 0 [1..10]


''suma'' toma una lista de valores y la reduce a un solo valor. Puede escribirlo como un bucle explícito (recuerde que Haskell no tiene palabras clave de bucle, pero usa recursividad). Observe cómo la definición tiene dos partes, según la forma de la lista:

mysum [] = 0 mysum (x:xs) = x + mysum xs

O más eficientemente, en un estilo recursivo de cola :

mysum xs = go 0 xs where go n [] = n go n (x:xs) = go (n+x) xs

Sin embargo, Haskell tiene una rica biblioteca de estructuras de control que operan en listas perezosas. En este caso, la reducción de una lista a un solo valor se puede hacer con una función de reducción: un pliegue.

Así que mysum se puede escribir como:

mysum xs = foldr (+) 0 xs

Por ejemplo:

Prelude> foldr (+) 0 [1..10] 55

Su error fue utilizar un mapa , que transforma una lista, un elemento a la vez, en lugar de un pliegue .

Le sugiero que comience con una introducción a Haskell, tal vez " Programación en Haskell ", para tener una idea de los conceptos básicos de la programación funcional. Otros buenos materiales introductorios se describen en esta pregunta.