Hi !
I’ve been trying to spend some time with Haskell for long but college.. assignments … etc..were keeping me away. Finally got time + kick + excitement last night and decided to code something meaningful.
Thought to solve this challenge one more time > http://punetech.com/apply
Its quite simple. Read from input.txt [which is actually a twitter feed] > remove duplicate id entries > sort in descending order of Timestamp and save to output.txt.
Took pretty long time though. I was also reading relevant pages from RWH. had to read some things like Monads twice/thrice to understand. Then talking to folks in IRC #Haskell.. Still have to go through alot.
but it was fun. yeah! my first Haskell program that works as expected
here’s the code. It still requires alot of cleaning and will do that after posting this. but this is the final v1.0 that works. So wanted to share this one only
--pune.hs
-- to solve challenge program given here > http://punetech.com/apply/
import System.IO
import List
main :: IO()
main = do
-- openFile returns a Handle
inh <- openFile "pInput.txt" ReadMode
-- get all the contents from input file
inputData <- hGetContents inh
-- get file contents split into array
let pData = lines inputData
-- store all lines in a list of Tweet data type
let tweets = getTweets pData
-- Remove duplicate entries
-- nubBy function removes duplicate entries
-- first argument is a 'comparer function'
-- second argument is list on which it works
let nDup = List.nubBy tweetEq tweets
-- Sort in descending order of timestamp
-- first argument is ordering function
-- second argument is list to work on
let sDup = List.sortBy tweetOrd nDup
-- open file for writing. openFile returns a Handle
outh <- openFile "pOutput.txt" WriteMode
-- send Handle and data to write to file
writeToFile outh sDup
--close both Handles
hClose inh
hClose outh
-- Custom data type to store a tweet
data Tweet = Tweet {
tid :: Int,
name :: String,
time :: Double,
message :: String
}deriving(Eq,Show)
-- function that equates two Tweets
-- passed to nubBy
tweetEq :: Tweet -> Tweet -> Bool
tweetEq t1 t2 = (tid t1) == (tid t2)
-- function that checks order
-- passed to sortBy
tweetOrd :: Tweet -> Tweet -> Ordering
tweetOrd t1 t2 = compare (time t2) (time t1)
-- convert Tweet Lines into List of Tweets
getTweets :: [String] -> [Tweet]
getTweets [] = []
getTweets (x:xs) = let parts = split x '|' in
let temp = Tweet{
tid = read (parts !! 0),
time = read (parts !! 1),
name = (parts !! 2),
message = (parts !! 3)
}
in [temp] ++ (getTweets xs)
-- no comments
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
| c == delim = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = split cs delim
-- no comments
writeToFile :: Handle -> [Tweet] -> IO()
writeToFile outh [] = hPutStrLn outh ""
writeToFile outh (x:xs) = do
let line = (show(tid x)) ++ "|" ++ (show(time x)) ++ "|" ++ (name x) ++ "|" ++ (message x)
hPutStrLn outh line
writeToFile outh xs
sweet !