top | item 7991451

(no title)

orangeduck | 11 years ago

I think this demonstraights a real weakness of Haskell. Several times I've started a new project only to spend several hours trying to work out the correct way to structure what I want. Often it is hours before I even get my first successful compile. This is exactly as shown in this blog post. While some people enjoy this kind of tinkering, for me this really quickly saps all my motivation for the task. I just want to get something, anything, working. I work best jumping directly into a task and understanding it from the inside out, learning from my mistakes. Sometimes if I do find a quick and dirty way to get something working in Haskell - often refactoring it also becomes pretty difficult - which turns me off again. Neither of these are problems I have in other languages.

Arguments for which approach is better aside, it is no wonder lots of people who learn and approach tasks like me, feel a little betrayed by Haskell. I've used it for a bunch of things, I'm past the steep learning curve - but it seems I'm still not reaping the rewards. Is my philosophy of jumping into projects really so bad? Is it Haskell's place to question such an approach, when it has served me so well elsewhere?

discuss

order

friendly_chap|11 years ago

It takes practice to be as fluent in FP as in imperative programming. When I've got the basics I still couldn't perform as quickly in Haskell as in other languages. Took me at least a year to become quick and apart from the weak library support (most things are a bit over the top for the beginners), I find Haskell amazingly productive. It's not _that_ different after you get used to it. Not having to write an other for loop ever again in a language which does't support generics alone worths it.

The language itself if you don't venture too far into the depths of the latest research is quite comfortable and clean. The fact that I can express my thoughts effortlessly in a few keystrokes and that the types (ADT, generics, typeclasses) are so descriptive makes it my favourite language for day to day tasks.

At least for the time being... until a dependently typed language becomes usable.

reikonomusha|11 years ago

I agree.

Haskell enforces a programmer to create structure. There's no way around it. And it's (nearly) impossible to hack things together without failing early and often.

As a result, before the problem you're trying to solve can be explored, you're stuck making guesses on how the problem should even be structured. You spend a few hours with one guess, it turns out to not get your far, and you try another.

The unfortunate part is that these guesses aren't letting you get to the meat of the problem effectively; you're stuck trying to solve a meta-problem.

Of course, once you have solved the meta-problem well enough, you can start exploring your problem. Unfortunately, you may find that your meta-solution doesn't actually let you answer questions you didn't know you wanted to answer from the get-go, and now you're back to square-one.

When everything is right, the program is usually very beautiful, safe, and—if you're skilled enough—efficient.

Perhaps not all Haskell programmers have this issue for very non-trivial programs, though I certainly do.

lclarkmichalek|11 years ago

I don't really agree. The greatest structure in most of my Haskell programs is some kind of ErrorT or something. That requires me to structure the way I handle IO and the way that Errorable things happen, but beyond that, `a` is just as generic as any Python type. Sure, a lot of libraries do require you to accept certain premises, which may be a problem, but most of them provide ways to break out of their abstractions: ErrorT provides `runErrorT :: (Monad m, Error e) => ErrorT e m a -> m (Either e a)` which allows me to break out very easily, and due to the composable nature of Haskell, even if the library does not provide a function, it is often far from hard to write one yourself.

tinco|11 years ago

I agree that Haskell forces the programmer to create structure, but I don't agree with your meta-problem hypothesis. I think the structure actually is a big part of the real problem, and Haskell just prevents you from implementing incomplete or incorrect solutions.

Those solutions might in another language require a hack or leaky abstractions to work, if they would be possible to get to work at all.

I've walked into problems like the OP has before with Haskell, and when there seems to be no nice way of defining a type structure to model the problem, it usually meant that the idea in my head had a fundamental problem. If I look at this tree I get the feeling that perhaps he just has two problems, and he's looking at it like he's got only one.

And once you do get your type structure neatly in place, often times the implementation will just flow out of your fingertips. And when it does, it will be powerful, flexible and robust.

lelf|11 years ago

It's more like your weakness, and I don't see want it has to do with Haskell. And if you really don't want to think about correct types just use the first came to your head. You can always change them later. And the compiler will tell you every single place your forgot to change.

kachnuv_ocasek|11 years ago

I agree with this. If it's not natural for you to think ahead, create the structure you need before writing it up, Haskell is not the right language for you. It's good there are languages that fit your needs, nonetheless.

radmuzom|11 years ago

Very true. I remember reading in StackOverflow where a guy commented that while programming in Haskell he was thinking more and programming less - he seemed to indicate that this was the most important thing. While design and structure is important, I think the reason he was "thinking so much" is that Haskell forces you to think non-trivially even for simple problems in many cases. One common argument made is that a loop is much more natural in many real-life scenarios rather than recursion or folds - so the mental model of the problem matches closely with the machine model - which is not the case when you are forced to use recursion.

lclarkmichalek|11 years ago

I completely disagree. And I'd go so far as to say that a lot of that criticism comes from a lack of familiarity in functional programming/Haskell compared to imperative programming. The argument of a loop being more realistic is horrible imo, as both refer to performing processes, which are abstract concepts: my mind probably views these differently to yours, and most likely very differently to a lay person, who will never have had to consider the idea.

I gave a talk recently, and I briefly explained how to decode a protocol buffer varint: if the last bit of a byte is true, shift the first 7 bits and repeat the process on the next byte. Does that map better to

    getVarInt :: G.Get Int
    getVarInt = G.getWord8 >>= getVarInt'
      where getVarInt' n
              | testBit n 7 = do
                m <- G.getWord8 >>= getVarInt'
                return $ shiftL m 7 .|. clearBit (fromIntegral n) 7
              | otherwise = return $ fromIntegral n
or

    def read_varint(self):
      run, value = 0, 0

      while True:
        bits = self.read(8)
        value |= (bits & 0x7f) << run
        run += 7

        if not (bits >> 7) or run == 35:
          break

      return value
I'm perfectly happy saying it is equally well represented on both of them. I know I much prefer the first, but that's probably just because I prefer recursion to an explicit loop. From the sounds of it, you'd prefer the second, and I believe that's just because you prefer loops to recursion.

Peaker|11 years ago

I think the real problem here, and it is a true problem with Haskell development, is perfectionism.

Code in Haskell can be so elegant, and examples of beautiful code are so abundant, that hacking together a bunch of hacks to see if they work doesn't seem like a conceivable way of doing things.

But of course, Haskell can be used that way to figure out and explore your problem. You can throw IORefs around, do everything with ugly IO effects, pass tons of parameters around, etc.

seanmcdirmid|11 years ago

Perfectionism is a problem I had with Scala awhile back. My penance was to program for the next 7 years in C# (at least I didn't go back to java). Sometimes no hope for achieving elegance can be empowering in getting things done.

I don't think Haskell is at all designed for quick and dirty prototyping and exploration. The whole library and tool mindset is against that kind of developer activity.