Simple Haskell program not behaving correct -
i'm new haskell , trying write simple program find maximal element , it's index intput. receive values compare 1 one. maximal element i'm holding in maxi variable, it's index - in maxidx. here's program:
loop = let maxi = 0 let maxidx = 0 let idx = 0 let idxn = 0 replicatem 5 $ input_line <- getline let element = read input_line :: int if maxi < element let maxi = element let maxidx = idx hputstrln stderr "inner check" else hputstrln stderr "outer check" let idx = idxn + 1 let idxn = idx print maxidx loop even though know elements coming starting bigger smaller (5, 4, 3, 2, 1) program enters inner check time (it should happen first element!) , maxidx 0. doing wrong? in advance.
anyway, let's have fun.
loop = let maxi = 0 let maxidx = 0 let idx = 0 let idxn = 0 replicatem 5 $ input_line <- getline let element = read input_line :: int if maxi < element let maxi = element let maxidx = idx hputstrln stderr "inner check" else hputstrln stderr "outer check" let idx = idxn + 1 let idxn = idx print maxidx loop is not particularly haskelly code (and know not particularly correct).
let's make if haskellier.
what here? we've infinite loop, reading line 5 times, it, , calls again no particular reason.
let's split it:
import control.monad readfivelines :: io [int] readfivelines = replicatem 5 readln addindex :: [int] -> [(int, int)] addindex xs = zip xs [0..] findmaxindex :: [int] -> int findmaxindex xs = snd (maximum (addindex xs)) loop :: () loop = loop main :: io () main = xs <- readfivelines putstrln (show (findmaxindex xs)) snd returns second element tuple; readln read . getline; zip takes 2 lists , returns list of pairs; maximum finds maximum value.
i left loop intact in original beauty.
you can haskellier if remember something (huge expression) can replaced something $ huge expression ($ applies left operand right operand), , functions can combined .: f (g x) same (f . g) x, or f . g $ x (see? it's working left side well!). additionally, zip x y can rewritten x `zip` y
import control.monad readfivelines :: io [int] readfivelines = replicatem 5 readln addindex :: [int] -> [(int, int)] addindex = (`zip` [0..]) findmaxindex :: [int] -> int findmaxindex = snd . maximum . addindex main :: io () main = xs <- readfivelines putstrln . show . findmaxindex $ xs as debug print, there's package called debug.trace , function traceshow prints first argument (formatted show, hence name) stderr, , returns second argument:
findmaxindex :: [int] -> int findmaxindex = snd . (\xs -> traceshow xs (maximum xs)) . addindex that allows tap onto expression , see what's coming in (and values around — can show tuples, lists, etc.)