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.)