1
votes

In my beginning functional programming class, I'm trying to write a program to return the middle third of a given list. As far as I know, the most straightforward way to do this would be take the first two thirds of the list, then drop the unwanted first third, returning only the middle third. However, I just can't seem to get the syntax right.

middlethird :: [a] -> [a]
middlethird l
    |len `mod` 3 /= 0 = []
    |otherwise        = drop (1 `div`take ((2 `div` 3) len) l drop ((1 `div` 3)*len) l
    where len = length l

Now I'm getting a parse error on 'where', which I don't understand... but even before that I was just getting an empty set for every list that I input, when it should only return an empty list when the length of the list isn't evenly divisible by 3.

I'm quite confused... any help or pointers would be greatly appreciated. As I mentioned, this is part of a homework assignment, but it's the very last part, and everything else seems to be running fine. Sorry for my inexperience!

EDIT: Nevermind, I figured it out.

middlethird :: [a] -> [a]
middlethird l
    |mod len 3 /= 0 = []
    |otherwise =  drop (div len 3) (take (2*(div len 3)) l)
    where len = length l
2
How about thinking about it like this: let n be one third of the length of the list. Now you want to drop n from the list and take n of the remainder.Tom Crockett

2 Answers

2
votes

Haskell uses a "layout" style syntax with significant whitespace, much like Python. In this case, since both middlethird and where are equally indented, the parser thinks where is supposed to be a new function definition and it gets bothered since you can redefine keywords.

Furthermore, you have too many open parens in your otherwise branch.

2
votes

It's not at all clear how you think your code is supposed to work. It looks like you try to divide numbers by lists, and call numbers as functions, both of which are 100% illegal and you know it – you just don't realise that's what happens in your code. Could you write step–by–step what you are trying to do, with more variables? Like this maybe:

last_two_thirds_start_at = (2 * len) `div` 3
list_of_first_two_thirds = take ... l
...
list_with_middle_third = drop ... list_of_last_two_thirds

Be really explicit about it. Test each step in the interpreter so you know it does what you think it does. I'm absolutely certain you can figure this out by yourself if you just stop panicking and stop getting yourself stuck in a sea of parentheses!