0
votes

I don't understand why this won't load into the interactive Haskell interpreter. When I type the function definition directly into GHCI it works just great. But when I try to load the function definition from a .hs file, that's when I get an error message. Any ideas? Thanks for the help.

let partialsums lst = reverse ( partial_sums lst 0 [] ) where
                      partial_sums ls accum accumulator_list = 
                      if ls == [] then accumulator_list else
                      partial_sums ( tail ls ) ( accum + head ls ) 
                      ((accum + head ls) : accumulator_list)

I've tried this same function definition in Python, Ruby and Ocaml. No problems at all! ( Python's whitespace rules are simple and intuitive. Ruby and Ocaml do not read whitespace. In those languages whitespace is strictly there for the convenience of the person reading the program. But I think Haskell has some pretty strict whitespace rules that I'm not familiar with. )

Thanks for the help. Haskell sure looks interesting, but it's a hard, hard language to learn without the supervision or guidance of a good professor. I'm just trying to learn the language on my own.

2
You code violates the indentation rules: see e.g. here for a quick summary.chi

2 Answers

5
votes

it's not the whitespaces - it's the let (and you have to indent the body of partial_sums as chi mentioned - sorry I didn't check this at first):

if you want to define the function in a .hs file you should write something like this:

partialsums lst = reverse ( partial_sums lst 0 [] ) where
                  partial_sums ls accum accumulator_list = 
                     if ls == [] then accumulator_list else
                     partial_sums ( tail ls ) ( accum + head ls ) 
                     ((accum + head ls) : accumulator_list)

although I would write it more like this:

partialsums lst = reverse ( partial_sums lst 0 [] ) 
   where
      partial_sums ls accum accumulator_list = 
         if ls == [] 
         then accumulator_list 
         else
            partial_sums ( tail ls ) ( accum + head ls ) 
                  ((accum + head ls) : accumulator_list)

improving on it

I would further suggest to add a signature and to use pattern-matching instead of the if, head and tail like this:

partialsums :: Num a => [a] -> [a]
partialsums lst = reverse ( partial_sums lst 0 [] ) 
   where
      partial_sums [] _ accumulator_list = accumulator_list
      partial_sums (h:tl) accum accumulator_list =
            let accum' = accum + h in
            partial_sums tl accum' (accum' : accumulator_list)

all should give you:

> partialsums [1..5]
[1,3,6,10,15]

using scanl1

fun fact: you can actually use scanl1 to define this very easy:

partialSums :: Num a => [a] -> [a]
partialSums = scanl1 (+)
0
votes

Thanks for the great answers! When is it appropriate to use the "let" keyword? Yes, that's exactly why I could not load my function definition into GHCI.

I've also been playing around with Python. Python's list comprehensions are just wonderful. In Python the partialsums function could be written like this:

def partialsums(array): return [sum([array[n] for n in range(0, t + 1)]) for t in range(0, len(array))]

I know Haskell uses list comprehensions as well, but for Haskell the syntax is a little different. Any ideas on how I could do something similar in Haskell? Thanks for the help! ( Don't worry. This is not for a class. I'm just trying to figure out Haskell on my own. I thought I would try it. A fun language, but definitely challenging. )