Hacker News new | ask | show | jobs
by bsznjyewgd 4036 days ago
>recursion and restricting all their programs to be a singular composite of expressions

Simple effect-free loops in an imperative language translate directly to a recursive function, which is just a labeled loop that makes explicit what/how state is manipulated each loop iteration.

(Edit: For effectful loops, it's common practice in imperative languages to interleave the effects with the program logic. (Un?)fortunately, Haskell discourages this practice and encourages you to refactor the pure parts of your program from the effectful parts. This might make your program more reusable and testable, but it's an obstacle if you are just writing a fancy Hello World and want to get stuff done.)

The singular composite of expressions is not a necessity, but to avoid it you have to give names to all your intermediate states, whereas a typical imperative language reuses the same name repeatedly.

3 comments

>Haskell discourages this practice and encourages you to refactor the pure parts of your program from the effectful parts.

No more than imperative languages do. Speaking from experience, if you wanna slap IO on the arse of all your types, no one can stop you. Our friggin' project/dependency management tool is written like this. Yes, Haskellers usually prefer something nicer but nobody's going to steal your compiler if you don't.

We should avoid mistaking our discomfort with a language or idiom with what it does or does not encourage, can or cannot do. Chopin's nocturne op 48 1 is not difficult because pianos discourage it, it's difficult because it's difficult. In fact, it would be extremely hard to translate to a less expressive instrument. Similarly, writing programs in a well-factored design that separate actions from the computations that decide what happens from the datatypes that model them takes effort and practice, whether you use Haskell or not. I would submit that using a less expressive language will not make the task itself easier any more than trying to capture all the notes of Chopin's 48/1 on something less expressive than a piano would be easier.

My coauthor has her 10 year old learning Haskell from our book. This stuff does not have to be hard.

I can do whatever I want in Haskell.

    Prelude> map (+1) [1..5]
    [2,3,4,5,6]

    Prelude> mapM_ (print . (+1)) [1..5]
    2
    3
    4
    5
    6
I've got more news for you, since we have composition for things with more structure, it's still composable. (>=>) is like function composition, but for when we have monadic structure flying around.

    Prelude> let x num = print num >> return (num + 1)
    Prelude> :t x
    x :: (Show b, Num b) => b -> IO b
    Prelude> mapM (x >=> x >=> x) [1..5]
    1
    2
    3
    2
    3
    4
    3
    4
    5
    4
    5
    6
    5
    6
    7
    [4,5,6,7,8]
You can write all the loopy-woopy side-effecty whatevers you want. Haskell's just better at it and offers alternatives. The actual recursive loops are less spooky than the name "mapM_", but I didn't want to make it verbose.

One of the nice things about Haskell is you can always replace a function with its contents, or factor something out into a function and call that function by name and the result never changes.

    -- You could inline the definition of foldr
    -- and make mapM_ loopy-woopy, but why would
    -- you want to repeat yourself?
    mapM_ = foldr ((>>) . f) (return ())
Hey I agree, I'm saying a beginner, like a beginner in programming in general.
If they already learned imperative language concepts, sure it's discouraging because people who know things don't like to go back to being beginners again.

But if they're completely starting from scratch, I'm not convinced it's really harder.

After all, apparently a ten year old can learn Haskell: https://superginbaby.wordpress.com/2015/04/08/teaching-haske...

The singular composite of expressions is not a necessity, but to avoid it you have to give names to all your intermediate states, whereas a typical imperative language reuses the same name repeatedly.

Interesting way to put it.

I like to tell people that they program in languages where every type signature is "Any -> IO Any". It's technically true, but it gets some weird looks.

Last weekend at LambdaConf (functional programming conference in Boulder) we were joking that all programming is fundamentally just a function of String -> Any.

Fewer weird looks when you make that joke surrounded by Haskellites and Scalaistas.

How was LambdaConf, by the way? I wasn't able to make it this year but I'd like to go next year.
It was great. Definitely looking forward to 2016.