4 ms·
> On one hand, 'imperative' means 'a list of operations > that produce a sequence of results'. We contrast that > with 'declarative programming', which m
by Dove 16y ago
> On one hand, 'imperative' means 'a list of operations
> that produce a sequence of results'. We contrast that
> with 'declarative programming', which means 'a list of
> results which are calculated (somehow) each step of the
> way'. Mathematical proofs and SQL queries are
> declarative. Most of the things we think of as
> programming languages are 'imperative' by this meaning,
> though, including most functional languages. No matter
> how you slice it, Haskell is not declarative.
Either I'm confused or the author is.
SQL is declarative, sure, but I don't think mathematical proofs are. Sometimes you do declarativeish things like, "Let x be the solution, known to exist, to this unsolvable problem." But I think the structure is fundamentally very imperative; ignoring the syntactic sugar, formal mathematical logic is a sequence of logical transformations that leads from hypothesis to conclusion.
I can chalk that up to confusion or inexperience on the author's part, but the bit about Haskell really confuses me.
I'm still quite new to functional programming -- just emerging from the "how the heck do I do that without for loops?" phase -- and the experience really has been one of learning to program all over again. As in the CS 101 days of yore, I have to spend a lot of time trying to figure out how to accomplish simple things, dealing with alien logical consequences and constructs.
Now, Scala lets me do things either way, and I like to think I'm getting to the point where that's an advantage rather than a crutch. But looking back over the last little while, I can't imagine how you could possibly slice Haskell in such a way that it's declarative at all. I mean, I've been banging my head against the relentless declarativity of it for a while. I'd like to think if there were crutches, I'd have found them.
Unless the author is talking about something silly, like the fact that it's ultimately compiled down to an imperative language to run on a real processor . . . I can't figure out what he's talking about. And I don't know whether to chalk that one up to confusion on his part or inexperience on mine.
- jmillikin 16y agoThe author is very confused. "Declarative" and "imperative" are just syntactic styles. Haskell supports both For example, the following Haskell expressions are equivalent: dec :: [Integer] dec = map (* 2) [1..10] imp :: [Integer] imp = do x <- [1..10] return (x * 2) Due to their origins, stateful languages are traditionally imperative, and functional languages are traditionally declarative. But please don't confuse the two sets of terms. Stateful | | | | Imperative | Declarative -----------------+------------------ | | | | | Functional
- icandoitbetter 16y agoCan you explain the imperative code? I understand that it has to do with lists being monads and all, but I don't get why (return ([1..10]*2)) :: [Integer] doesn't work. What's the magic behind x <- [1..10] ?
- tkahn6 16y agoThat `do` expressions is equivalent to [1..10] >>= (\x -> return (x * 2)) and the definition of (>>=) for a List monad is instance Monad [] where return a = [a] xs >>= f = concat (map f xs) `xs` becomes bound to [1..10] `f` becomes bound to (\x -> return (x * 2)) we we map `f` over each element in the list and get mini-lists. `x` gets bound to each element in the list, x is multiplied by 2, and then returned into a list (1 becomes [2], 2 becomes [4], and so on). So we get: concat [[2],[4],[6]..[20]] And then we concatenate the mini-lists together to get. [2,4..20] As an aside, this is also equivalent [1..10] >>= return . (* 2)
- icandoitbetter 16y agoThanks!
- Dove 16y agoThanks for that. I did know about the do syntax in Haskell, but I didn't think it really made the language usefully imperative. Sure, it's okay if you're trying to kick off two or three unrelated calculations, maybe if you're after side effects. But I didn't find it much to fall back on when trying to do something complicated and having a hard time thinking about how to break down the problem without for loops and case statements and value accumulators. Maybe it's more robust than I know, but it seems like such a small piece of such a big language. Calling Haskell imperative on account of that seems like calling perl OO because you can kinda sorta do basic OO stuff most of the time. I am also having trouble understanding the claim that the ideas are orthogonal. I can see plainly enough that they aren't literally the same thing: an imperative language breaks a problem down into simpler steps, while a declarative one breaks a problem down into simpler definitions. And a stateful language accumulates progress in changing values, while a functional language does so by resolving expressions. So far so good, but I can't really decouple the concepts. How would you break a problem down by time, but track results through logical resolution? Isn't the point of a step or instruction to leave something about the state of the program changed--I mean, isn't it inherently stateful? It seems to me the advantage of imperative programming is that the steps are logically decoupled, just as the advantage of declarative programming is that the pieces are temporally decoupled. So how in the world would you make a declarative program accumulate progress via state?
- andrewflnr 16y agoAs I understand, a mathematical proof is a declaration that certain transformations are possible. Really, it just points out truths that already exist.