 crazy4groovy
3/15/2013 - 12:59 AM

``````// This is a comparison between Haskell and Groovy based on some simple problems found in the following

// Ex 1. If we have two lists, [2,5,10] and [8,10,11] and we want to get the products of all the possible
// combinations between numbers in those lists, here's what we'd do.

[ x*y | x <- [2,5,10], y <- [8,10,11]]

/* Groovy */
{ [2,5,10].collect { x -> [8,10,11].collect { y -> x * y } }.flatten() }

// Ex 2. What if we wanted all possible products that are more than 50?

[ x*y | x <- [2,5,10], y <- [8,10,11], x*y > 50]

/* Groovy */
{ [2,5,10].collect { x -> [8,10,11].collect { y -> x * y } }.flatten().findAll{ it > 50 } }

// Ex 3. How about a list comprehension that combines a list of adjectives and a list of nouns … for epic hilarity.

/* Groovy */

// Ex 4. Let's write our own version of length! We'll call it length'.

length' xs = sum [1 | _ <- xs]

/* Groovy */
length = { xs -> xs.inject { acc, _ -> acc += 1 }  }

// Ex 5. Here's a function that takes a string and removes everything except uppercase letters from it.

removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]

/* Groovy */
removeNonUppercase = { st -> st.inject { acc, c -> acc + ( ('A'..'Z').contains( c ) ? c : '' ) } }

// Ex 6. A list contains several lists of numbers. Let's remove all odd numbers without flattening the list.

[ [ x | x <- xs, even x ] | xs <- xxs]

/* Groovy */
{ xxs -> xxs.inject([]) { res, xs -> res << xs.findAll { x -> x % 2 == 0 } } }

// Ex 7. ... let's try generating all triangles with sides equal to or smaller than 10:

let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]

/* Groovy */
def triangles = { def res = []
(1..10).each{ a -> (1..10).each{ b -> (1..10).each{ c -> res << [a,b,c] } } }
res
}

// Ex 8. ... we'll add a condition that they all have to be right triangles.
// We'll also modify this function by taking into consideration that side b isn't larger
// than the hypothenuse and that side a isn't larger than side b.

let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]

/* Groovy */
def rightTriangles = { def res = []
(1..10).each{ c -> (1..c).each{ b -> (1..b).each{ a -> if ( a**2 + b**2 == c**2 ) res << [a,b,c] } } }
res
}

//############### Doing some I/O ###############//

// Ex 9. Read file and print its contents

import System.IO

main = do
putStr contents

/* Groovy */
new File("girlfriend.txt").eachLine{ println it }

// Ex 10. Convert a file's text to ALL CAPS text and save it in another file

import System.IO
import Data.Char

main = do
writeFile "girlfriendcaps.txt" (map toUpper contents)

/* Groovy */
def input = new File("girlfriend.txt")
new File("girlfriendcaps.txt").withWriter { w -> input.eachLine{ w.writeLine it.toUpperCase() } }

// Ex 11. Given a text file containing TO-DO tasks, remove a line chosen by the user from the file

import System.IO
import System.Directory
import Data.List

main = do
(tempName, tempHandle) <- openTempFile "." "temp"
contents <- hGetContents handle
numberedTasks = zipWith (\n line -> show n ++ " - " ++ line) [0..] todoTasks
putStrLn "These are your TO-DO items:"
putStrLn "Which one do you want to delete?"
numberString <- getLine
hPutStr tempHandle \$ unlines newTodoItems
hClose handle
hClose tempHandle
removeFile "todo.txt"
renameFile tempName "todo.txt"

/* Groovy */
def todoFile = new File('/tmp/todo.txt')
todoFile.eachLine { todoTasks << it }
println 'These are your TO-DO items:'
println "\${index + 1} - \$todo"
}
def numberString = System.console().readLine 'Which one do you want to delete?'
todoFile.withWriter { out ->
}

// Ex 12. Create a SQL database with a single table, add data to it, then print the contents of the table

// Using Sqlite database for convenience: http://www.sqlite.org/
:module Database.HDBC Database.HDBC.Sqlite3
conn <- connectSqlite3 "test1.db"
run conn "CREATE TABLE test (id INTEGER NOT NULL, desc VARCHAR(80))" []
run conn "INSERT INTO test (id, desc) VALUES (?, ?)" [toSql 123, toSql "DB stuff"]
commit conn
res <- quickQuery conn "SELECT * FROM test"
let stringRows = map convRow res
mapM_ putStrLn stringRows
disconnect conn
where convRow :: [SqlValue] -> String
convRow [sqlId, sqlDesc] =
show intid ++ ": " ++ desc
where intid = (fromSql sqlId)::Integer
desc = case fromSql sqlDesc of
Just x -> x
Nothing -> "NULL"
convRow x = fail \$ "Unexpected result: " ++ show x

/* Groovy */
// Much more convenient to use H2 in Java/Groovy: http://www.h2database.com
import static groovy.sql.Sql.newInstance

sql.execute 'CREATE TABLE test (id INTEGER NOT NULL, desc VARCHAR(80))'
sql.execute 'INSERT INTO test (id, desc) VALUES (?, ?)', [123, 'DB stuff']
sql.eachRow( 'SELECT * FROM test' ) { println "\${it.id}: \${it.desc}" }

//############### GUI Stuff ###############//

// Ex 13. Create a window with a menu-bar containing a File menu with 2 items - About.. and Quit
// At the bottom of the window, there should be a status bar displaying some help for the currently

{- demonstrates the use of a simple menu, statusbar, and dialog -}
module Main where

import Graphics.UI.WX

main :: IO ()
main
= start hello

hello :: IO ()
hello
= do -- the application frame
f      <- frame         [text := "Hello world!", clientSize := sz 300 200]

file   <- menuPane      [text := "&File"]
quit   <- menuQuit file [help := "Quit the demo", on command := close f]

-- create statusbar field
status <- statusField   [text := "Welcome to wxHaskell"]

-- set the statusbar and menubar
set f [ statusBar := [status]
-- as an example, put the menu event handler for an about box on the frame.
]

/* Groovy */

import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
import static javax.swing.JOptionPane.showMessageDialog as showDialog
import static javax.swing.JOptionPane.INFORMATION_MESSAGE as INFO

def about = { showDialog null, "This is a Groovy demo", "About Groovy", INFO }

new SwingBuilder().edt {
def status
def defaultStatus = "Welcome to Groovy SwingBuilder"
frame( title:'Hello world!', size: [ 300, 200 ], show: true) {
borderLayout()
mouseEntered: { status.text = "About Groovy" },
mouseExited: { status.text = defaultStatus } )