1270: Functional

This forum is for the individual discussion thread that goes with each new comic.

Moderators: Moderators General, Prelates, Magistrates

rmsgrey
Posts: 3052
Joined: Wed Nov 16, 2011 6:35 pm UTC

Re: 1270: Functional

Postby rmsgrey » Mon Dec 16, 2013 10:56 pm UTC

Kit. wrote:An interaction of Turing machine with a user can be achieved by halting the machine before the user input and restarting it after the input. The tape content can be arranged in the following way:

at halt:
persistent-internal-status | machine-output

at restart:
persistent-internal-status | user-input

Each interaction will be a halt/restart cycle.


The trouble is, while each run is entirely computable, the editing of the tape between runs is not guaranteed to be computable...

Kit.
Posts: 1006
Joined: Thu Jun 16, 2011 5:14 pm UTC

Re: 1270: Functional

Postby Kit. » Tue Dec 17, 2013 8:13 am UTC

As long as it's the same for both functional and imperative equivalents (i.e. the difference between the implementations is not affecting the user's decisions), it's not a problem.

lalop
Posts: 210
Joined: Mon May 23, 2011 5:29 pm UTC

Re: 1270: Functional

Postby lalop » Tue Feb 03, 2015 7:39 pm UTC

With regard to the difficulty of understanding pure IO:

http://blog.jle.im/entry/io-monad-considered-harmful

“How does Haskell, a pure language, handle impure side-effects?”

...the answer is anything except “the IO Monad”. If I were to make a list of the most misleading, incorrect, dangerous, and disgusting possible answers, this would be on the top spot. The IO type itself is what enables this. Not the monadic interface.


The article's terminology is weird because IO is at least a type constructor: there is not only one IO type, but IO String, IO (), etc. But I think the point is sane: running a Haskell program - that is, calling its main function - yields an IO action, whose value specifies (to the interpreter/compiler?) what side-effects are to occur. Said action is constructed purely functionally. That said action is (for all but simple programs) formed using monadic constructs is interesting, but not directly related to the question.

The IO Monad does relate to obvious follow ups, e.g. "how do we form an IO action that is a chain of multiple IO actions", "how are non-IO functions used in above construction", "how is IO defined to support such things, and can I use similar concepts elsewhere", so I can see how the term got to be in use. But I agree with the author that the term is harmful, causing Haskell IO to be perceived as inscrutible before one has even started looking into the language!

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: 1270: Functional

Postby ahammel » Wed Feb 04, 2015 5:26 am UTC

If you're teaching Haskell from scratch, it might be best not to mention the Monad abstraction until you're talking about more than one Monad.
He/Him/His/Alex
God damn these electric sex pants!

lalop
Posts: 210
Joined: Mon May 23, 2011 5:29 pm UTC

Re: 1270: Functional

Postby lalop » Wed Feb 04, 2015 9:16 am UTC

True, but my concern is with the party line. Most of the answers I've seen on the internet, including old replies in this thread, immediately point out the IO Monad, scaring the reader away both from Haskell and from trying to understand pure IO in general. I also remembered my own confusion back when I was looking it up for this thread. Past me would probably have benefitted from the article, at least as a "mostly right" starting point.

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: 1270: Functional

Postby ahammel » Wed Feb 04, 2015 3:20 pm UTC

lalop wrote:True, but my concern is with the party line. Most of the answers I've seen on the internet, including old replies in this thread, immediately point out the IO Monad, scaring the reader away both from Haskell and from trying to understand pure IO in general. I also remembered my own confusion back when I was looking it up for this thread. Past me would probably have benefitted from the article, at least as a "mostly right" starting point.

Yeah, I'm with you. There's a commom misunderstanding that monads are inherently un-escapeable that I think comes from this "IO Monad" nonsense.

Some of the tutorials don't help.
He/Him/His/Alex
God damn these electric sex pants!

Boson Collider
Posts: 12
Joined: Wed Oct 29, 2014 6:20 pm UTC

Re: 1270: Functional

Postby Boson Collider » Mon May 16, 2016 1:52 am UTC

Really, I think a lot of the confusion about functional programming comes from a lot of programmers beginning in Python or Java, neither of which initially supported tail recursion. Therefore, the idea of programming without for or while loops seems alien.

So it might be a good idea to show a practical example of how Haskell does IO and a main loop at the same time: here is an example of an echo function. If you call it at any point in the main function of a command line program, it will prompt you for text, and write back what you wrote:

Code: Select all

let spam = readLn >>= putStr >> putStr "\n" >> spam


When you call the function, it calls readLn which prompts you for a string. The output is then shoved by the bind operator >>= (think of it like a unix pipe) into putStr, which prints out what you wrote. The >> bind operator is a dummy pipe that schedules an operation after the previous one without passing the outputs to inputs. We used it to schedule a newline to make our program look better, and after that the function calls itself, which loops us back to the beginning.

the >>= and >> pipes are the IO monad by the way. That's it. Doesn't look too weird when you describe it that way, now does it? These operators happen to satisfy the monad axioms, but you don't need to know that to use them. It just means they'll magically behave super intuitively and just work whenever you use them because of their deep properties.

The "have the function call itself to make the main IO loop" is one reason why tail recursion is more important in Haskell than in iterative languages: tail recursion is how you handle iterative problems in Haskell. Tail recursive functions behave iteratively. Instead of using a given loop function like for or while, you have the power to make one yourself with a tool (tail recursion) which is of comparable power to a goto.

The >>= and >> operators allow you to schedule IO-related operations, because the compiler sees that "the part on the right depends on the part on the left", so it executes the part on the left first. They allow sandboxing IO from pure functions because (up to syntactic sugar) they are the only way to pass IO data to and between pure functions. Together with tail recursion(possibly calling other functions instead of itself) you can use this to write any iterative IO program.

I think that the statement "there are no side effects in Haskell" scares people off unnecessarily. You can do a lot of side-effect-ish stuff, you just have to make it explicit in the syntax and the variable/function types of your code. You schedule events using data flow instead of time-ordering execution by line number.

User avatar
orthogon
Posts: 2644
Joined: Thu May 17, 2012 7:52 am UTC
Location: The Airy 1830 ellipsoid

Re: 1270: Functional

Postby orthogon » Mon May 16, 2016 11:40 am UTC

Boson Collider wrote:Instead of using a given loop function like for or while, you have the power to make one yourself with a tool (tail recursion) which is of comparable power to a goto.

You've pushed it too far this time. Now I'm 99% sure this whole Haskell thing is a wind-up.
xtifr wrote:... and orthogon merely sounds undecided.

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: 1270: Functional

Postby ahammel » Fri Jun 17, 2016 2:07 pm UTC

Boson Collider wrote:The "have the function call itself to make the main IO loop" is one reason why tail recursion is more important in Haskell than in iterative languages: tail recursion is how you handle iterative problems in Haskell.

In my experience, higher-order functions are a much more common way of handling iteration than direct recursion in Haskell. In fact, I would almost consider explicit recursion a code smell.

For instance, I would probably write your example function like this:

Code: Select all

let spam = forever $ readStr >>= putStrLn
He/Him/His/Alex
God damn these electric sex pants!

airdrik
Posts: 221
Joined: Wed May 09, 2012 3:08 pm UTC

Re: 1270: Functional

Postby airdrik » Fri Jun 17, 2016 9:45 pm UTC

Well, just because you don't write the recursion as part of you code which processes the stream of data doesn't mean there isn't recursion involved. It's just hidden behind layers of higher-order functions.

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: 1270: Functional

Postby ahammel » Sat Jun 18, 2016 1:18 am UTC

airdrik wrote:Well, just because you don't write the recursion as part of you code which processes the stream of data doesn't mean there isn't recursion involved. It's just hidden behind layers of higher-order functions.
Well, Haskell goes through C on its way to machine code, so there are probably for loops somewhere in there as well :wink:

Seriously though: tail recursion is definitely something you need a good handle on as an experienced Haskell programmer, but if it's what's scaring off newbies, then you're showing newbies the wrong things.
He/Him/His/Alex
God damn these electric sex pants!

Boson Collider
Posts: 12
Joined: Wed Oct 29, 2014 6:20 pm UTC

Re: 1270: Functional

Postby Boson Collider » Sat Jul 02, 2016 11:11 am UTC

Right, in practice you would often encapsule the recursion into a higher order function to make your code reusable, and generally to enjoy the benefits of structured programming. But the thing that allows you to do that is Tail recursion. You need a primitive as powerful as a goto to implement arbitrary loopy constructs at the library level rather than at the language primitive level, and optimized tail calls are much better suited for the task than gotos are.

The ability to make a loop yourself is important. For example, the "forever" loop has no break condition. If you wanted to make say, a program that echoed everything, unless you typed "quit" to make it stop, you need something with an exit condition. If you can't find a loop function in the libraries that explicitly implements the behaviour you want, you can write one yourself.


Return to “Individual XKCD Comic Threads”

Who is online

Users browsing this forum: CelticNot, mscha and 44 guests