Thursday, August 28, 2014

Mi primer post sobre Haskell

Así que...como me he metido en la programación funcional gracias a Erlang...decidí ir mas allá con Haskell...un lenguage de programación funcional puro...

Por supuesto...para esto estoy leyendo un libro...así que cuando lo termine...lo cual va a tomar un largo tiempo puesto que estoy pensando volver a leerlo desde la primera página...podrán leer mi review sobre Learn You a Haskell for Great Good...

Ahora...Haskell es dificil...el lenguaje de programación más dificil que alguna vez me he atrevido a aprender...y aquí hay algunas de las razones de porque es tan dificil...
  • Las variables son inmutables...una vez asignadas no pueden ser reasignadas.
  • Las funciones reciben un parámetro y nada más que un parámetro.
  • Las funciones solo pueden llamar a una función a la vez.
  • No hay loops.
  • No hay efectos secundarios...todo es puro...una función siempre va a devolver el mismo resultado

Hay una imagen muy buena de XKCD explicándo Haskell...


En fín...Haskell te hace olvidar todo lo aprendiste alguna vez y te hace aprender todo de nuevo...para un desarrollador como yo...eso es pura felicidad -:)

Así que...Como ya lo he hecho con Ruby, Python, Julia y Erlang...Quería que mi primer programa en Haskell fuera un aplicación de Números LED...así que ahí va el código...agarrense de sus asientos y vean esto...por cierto..estoy seguro de que mi código puede optimizarse...pero solo soy un principiante...y mi aplicación funciona...así que a quien le importa -;)


LED.hs
showLED :: Int -> IO()
showLED(num) = do
 putStr(concat(addN(get_led(digits num) 1 num) (length(show num)) (length(show num))))

get_led :: [Int] -> Int -> Int -> [[Char]]
get_led (x:xs) n num = make_led_digit(x,n) ++ get_led(xs) n num
get_led [] n num = get_led2(digits num) (n+1) num

get_led2 :: [Int] -> Int -> Int -> [[Char]]
get_led2 (x:xs) n num = make_led_digit(x,n) ++ get_led2(xs) n num 
get_led2 [] n num = get_led3(digits num) (n+1) num

get_led3 :: [Int] -> Int -> Int -> [[Char]]
get_led3 (x:xs) n num = make_led_digit(x,n) ++ get_led3(xs) n num
get_led3 [] n num = []

digits :: Int -> [Int]
digits = map (read . (:[])) . show

addN :: [String] -> Int -> Int -> [String]
addN (x:xs) n ni
 | n > 0 = [x] ++ addN xs (n-1) ni
 | n == 0 = ["\n"] ++ [x] ++ addN xs (ni-1) ni
addN [] _ _ = [] ++ ["\n"]

make_led_digit :: (Int, Int) -> [[Char]]
make_led_digit(0,1) = [" _  "]; make_led_digit(0,2) = ["| | "]; make_led_digit(0,3) = ["|_| "];
make_led_digit(1,1) = ["  "];   make_led_digit(1,2) = ["| "];   make_led_digit(1,3) = ["| "];
make_led_digit(2,1) = [" _  "]; make_led_digit(2,2) = [" _| "]; make_led_digit(2,3) = ["|_  "];
make_led_digit(3,1) = ["_  "];  make_led_digit(3,2) = ["_| "];  make_led_digit(3,3) = ["_| "];
make_led_digit(4,1) = ["    "]; make_led_digit(4,2) = ["|_| "]; make_led_digit(4,3) = ["  | "];
make_led_digit(5,1) = [" _  "]; make_led_digit(5,2) = ["|_  "]; make_led_digit(5,3) = [" _| "];
make_led_digit(6,1) = [" _  "]; make_led_digit(6,2) = ["|_  "]; make_led_digit(6,3) = ["|_| "];
make_led_digit(7,1) = ["_   "]; make_led_digit(7,2) = [" |  "]; make_led_digit(7,3) = [" |  "];
make_led_digit(8,1) = [" _  "]; make_led_digit(8,2) = ["|_| "]; make_led_digit(8,3) = ["|_| "];
make_led_digit(9,1) = [" _  "]; make_led_digit(9,2) = ["|_| "]; make_led_digit(9,3) = [" _| "]

Aquí hay una imagen que muestra como funciona...


Voy a seguir aprendiendo Haskell y escribir otro blog llamado "Decimal a Romanos - Al estilo Haskell"...manténganse en sintonía -;)

UPDATE!

Está bien...debo admitirlo...no podía dejar la aplicación así sabiendo que podía hacerla mejor...aquí está la versión actualizada -;)

LED_Fixed.hs
showLED :: Int -> IO()
showLED(num) = do
 putStr(concat(addN(get_led(digits num) 1 num) (length(show num)) (length(show num))))

get_led :: [Int] -> Int -> Int -> [[Char]]
get_led (x:xs) n num = make_led_digit(x,n) ++ get_led(xs) n num
get_led [] n num
 | n < 3 = get_led(digits num) (n+1) num
 | n == 3 = []

digits :: Int -> [Int]
digits = map (read . (:[])) . show

addN :: [String] -> Int -> Int -> [String]
addN (x:xs) n ni
 | n > 0 = [x] ++ addN xs (n-1) ni
 | n == 0 = ["\n"] ++ [x] ++ addN xs (ni-1) ni
addN [] _ _ = [] ++ ["\n"]

make_led_digit :: (Int, Int) -> [[Char]]
make_led_digit(0,1) = [" _  "]; make_led_digit(0,2) = ["| | "]; make_led_digit(0,3) = ["|_| "];
make_led_digit(1,1) = ["  "];   make_led_digit(1,2) = ["| "];   make_led_digit(1,3) = ["| "];
make_led_digit(2,1) = [" _  "]; make_led_digit(2,2) = [" _| "]; make_led_digit(2,3) = ["|_  "];
make_led_digit(3,1) = ["_  "];  make_led_digit(3,2) = ["_| "];  make_led_digit(3,3) = ["_| "];
make_led_digit(4,1) = ["    "]; make_led_digit(4,2) = ["|_| "]; make_led_digit(4,3) = ["  | "];
make_led_digit(5,1) = [" _  "]; make_led_digit(5,2) = ["|_  "]; make_led_digit(5,3) = [" _| "];
make_led_digit(6,1) = [" _  "]; make_led_digit(6,2) = ["|_  "]; make_led_digit(6,3) = ["|_| "];
make_led_digit(7,1) = ["_   "]; make_led_digit(7,2) = [" |  "]; make_led_digit(7,3) = [" |  "];
make_led_digit(8,1) = [" _  "]; make_led_digit(8,2) = ["|_| "]; make_led_digit(8,3) = ["|_| "];
make_led_digit(9,1) = [" _  "]; make_led_digit(9,2) = ["|_| "]; make_led_digit(9,3) = [" _| "]

Saludos,

Blag.
Development Culture.

No comments: