5 ms·
Could you elaborate? As a C guy, I'm interested what you think would be simpler than that simple code you posted. Structurally, what you just posted (minus the
by xamuel 8y ago
Could you elaborate? As a C guy, I'm interested what you think would be simpler than that simple code you posted. Structurally, what you just posted (minus the details about what "socket" and "listen" mean) could be understood by a child. I'm skeptical the corresponding Haskell >>= construction would be so understandable.
- tathougies 8y agoIn Haskell, the 'if (err) { ... }' parts could be factored out into a new bind operator for a new monad stack. Then, you don't have to write these checks every single time. The do notation is automatically converted into the corresponding monadic code, and the algebraic monad laws guarantee that the meaning of the code is preserved. For example, for the `if (err) {...}` cases, this is just the `ExceptT` monad transformer. With regard to understandability, using error throwing code in Haskell is really easy. Implementing it is slightly more difficult, but so is implementing a C compiler. I mean, we shouldn't judge the utility of a thing based on whether the implementation of the thing could be understood by a child. By that measure, children would be incapable of using facebook, because they could not build it.
- xamuel 8y agoSo what would the above code actually look like, in your world? >you don't have to write these checks every single time But in real-world applications, the way you react to errors would differ from function to function. Some functions would print a notification to a logfile and return early. Some would terminate the program and send an email to an admin. Some would activate a red "offline" indicator somewhere in a program.
- tathougies 8y agoIn haskell? I'd construct an API that could be used like the following. This looks like the code we write at the place i work at: runService= s <- note SocketConnectionError $ socket AF_INET ... note CouldNotListen $ listen s 5 note CouldNotBind $ bind s ... forever $ do client <- note CouldNotAccept $ accept s response <- serveRequest client ... The signatures of socket, bind, etc, would look like (for example): socket :: ExceptT SocketError IO Int listen :: Int -> Int -> ExceptT ListenError IO () Then, at top level main = runExceptT runService >>= either handleError pure handleError (SocketConnectionError rsn) = <try again, maybe> handleError ... The key here is that error handling is factored out. The 'runService' function expresses concisely all the steps taken, and the entire concern of error handling is factored out into the 'handleError' function, whose behavior I can actually change based on what I may want. In a C implementation, changing error handling strategies, would mean passing some kind of flag in (you could rebuild exceptions using setjmp/longjmp, but meh).
- lmm 8y agoChildren aren't born knowing C, and people who learn functional first don't tend to find it any harder. (If anything it's easier, since the meaning of "=" in Haskell is much closer to its usual meaning than the meaning in C).
- tathougies 8y agoYeah, I agree. Functional languages are often more intuitive to beginners. My pet theory is that the reason CS people tend to be somewhat 'odd' is that most people do not think imperatively, so when imperative programming is propped up as the gateway, it screens out people who would otherwise flourish in the field.
- magicalhippo 8y ago> most people do not think imperatively When trying to solve a problem by thinking it through, don't most people think imperatively? Ie by a sequence of steps (statements) that modify the world around them (state) to reach the goal?
- tathougies 8y agoI’m not a psychologist. I can’t talk about most people. I do not. I break problems down into sub problems and then think of how to combine results to achieve the answer. I repeat this until my subproblem is trivial. This lends well to the compositional approach of functional languages. Imperative languages require taking the extra step of scheduling. I think many people think like me but due to the prevalence of imperative languages, do not pursue cs.
- magicalhippo 8y agoWell, scheduling is important. I can't connect my new phone to the computer until I've taken it out of the box it came in. It feels like I'm leaning to the imperative side. When breaking down the problem into substeps, I'm already thinking about the sequencing which will later dictate the scheduling. I've been teaching Scratch[1] to 11-13 year olds for a few years now, and most seem to pick it up pretty quick. However a few struggle (while still being motivated enough to keep trying). Would be interesting to see how it went with a functional Scratch version. [1]: https://scratch.mit.edu/ https://scratch.mit.edu/
- dustingetz 8y agoC error checks are easy but not simple, you need enormous amounts of QA for every single change to know if you got it right (and then you still dont know)