I'm learning Haskell, and I've finally gotten around to coding up some Haskell. This code passed my tests.
This code takes a line from standard in which tells it how many cases it's going to have (1 to 5), and for each case, it takes a line telling it how many pairs (max of 100) of x's and y's it will get (integers from 0 to 500), and it should print
YES if x to y is a function, and
e.g. with a file called
2 2 1 1 2 1 2 1 1 1 2
The following command should work like this:
$ runhaskell main.hs < input YES NO
In my source code the only difference is I have two blank lines for style instead of one between each group of code. My
import Control.Monad (replicateM_, replicateM, forM) import Data.String (words) main = do times <- readLn :: IO Int replicateM_ times input_is_a_function input_is_a_function = do n_inputs <- readLn :: IO Int inputs <- replicateM n_inputs getLine if (null inputs) || (is_function inputs) then putStrLn "YES" else putStrLn "NO" is_function inputs = is_func ([map read $ words i | i <- inputs] :: [[Int]]) is_func (x_y : rest) | rest ==  = True | otherwise = (no_other_y x_y rest) && (is_func rest) no_other_y [x1, y1] rest | rest ==  = True | otherwise = this_y_ok && (no_other_y [x1, y1] (tail rest)) where this_y_ok = not (x_is_target && y_not_equal) x_is_target = x1 == head (head rest) y_not_equal = y1 /= ((head rest) !! 1) -- if target is false, y is ok. -- if target is True, y must be equal
The algorithm starts with the first pair of x and y, and does a search for a repetition of x and determines if it matches y or not. Any found x with a mismatch on y should stop the algorithm.
I come from a Python background, so I tend to use snake-case and idioms I am more immediately familiar with (list comprehensions FTW!), but I want to learn idiomatic Haskell.
I also value readability. I could probably have better names. Perhaps more typing would improve readability, but I tried to take as much advantage of Hindley-Milner type inference as I could.
Please address efficiency, typing, style, naming, or any other important issues you identify.
On my workflow: I've been using a basic ghc (7.10.3) from the Ubuntu repos with a test file and that command mentioned above.
Is there a better approach? e.g. a way to watch the file and run tests as I code and save? In Haskell?