Suma de serie de raíces

Ejercicio comparativo del mismo conjunto de funciones con C, Python y Haskell. En Haskell la función principal se resume a sumaSerieRaices a b = sum [sqrt i | i <- [a..b]]

El programa en Haskell

module Main where
import System.IO
import Text.Printf

main = do
         a <- pideLimite "inferior" 0   -- rechaza a < 0
         b <- pideLimite "superior" a   -- rechaza b < a
         printf "Suma de raíces de %f a %f: %f.\n"
                a b $ sumaSerieRaices a b
     
sumaSerieRaices a b = sum [sqrt ns | ns <- [a..b]]

pideLimite tipo minimo = do
                           temp <- prompt $ "Introduzca el límite " ++ tipo ++ ": "
                           if temp >= minimo      -- si es mayor o igual al minimo
                                 then return temp -- devuelve el valor introducido
                                 else do limiteErroneo minimo -- o recuerda el mínimo
                                         pideLimite tipo minimo -- y pide otro número

prompt s = putStr s >> hFlush stdout >> readLn :: IO Float

limiteErroneo = printf "El número no puede ser menor a %f\n\n"

El programa en Python

from math import *

# Pedir límites inferior y superior.
a = int(raw_input(’Límite inferior:’))
while a < 0:
    print ’No puede ser negativo’
    a = int(raw_input(’Límite inferior:’))

b = int(raw_input(’Límite superior:’))
while b < a:
    print ’No puede ser menor que %d’ %a
    b = int(raw_input(’Límite superior:’))

# Calcular el sumatorio de la raíz cuadrada de i para i entre a y b.
s = 0.0
for i in range(a, b+1):
    s += sqrt(i)

# Mostrar el resultado.
print ’Sumatorio de raíces’,
print ’de %d a %d: %f’ %(a, b, s)

El programa en C

#include <stdio.h>
#include <math.h>

int main(void)
{
  int a, b, i;
  float s;

  /* Pedir límites inferior y superior. */
  printf("Límite inferior:");
  scanf("%d", &a);
  while (a < 0) {
    printf("No puede ser negativo\n");
    printf("Límite inferior:");
    scanf("%d", &a);
  }

  printf("Límite superior:");
  scanf("%d", &b);
  while (b < a) {
  printf("No puede ser menor que %d\n", a);
  printf("Límite superior:");
  scanf("%d", &b);
  }

  /* Mostrar el resultado */
  printf("Sumatorio de raíces ");
  printf("de %d a %d: %f\n", a, b, s);

  return 0;
}
   

Nótese como la función en Haskell puede leerse casi exactamente como la función matemática pura:

sum [sqrt ns | ns <- [a..b]]
-- (sum)                        sumatoria
--  (sqrt ns)           de raíces de números
-- donde ns vienen de [a..b] <- rango de límites

Y según yo, aún varios de los comentarios en el código en Haskell son hasta superfluos (los nombres de funciones me parece que se entienden solos).

Por cierto para quien quiera un poco más de eficiencia en la función sumatoria, puede cambiar la comprensión de listas

sum [sqrt ns | ns <- [a..b]]

por una evaluación más estricta; por ejemplo:

sumRaices a b = foldl' (+) 0 map sqrt [a..b]@

Explicación:

foldl' (+) 0
— ligeramente más rápido que sum ; y

map sqrt [a..b]
— equivale a [sqrt ns | ns <-[a..b]];

para la función foldl' hay que insertar

import Data.List
— después de la primera línea
module Main..