Live data from Hacker News

Destroy All Ifs – A Perspective from Functional Programming

degoes.net

91–100 of 226 posts

Re: Destroy All Ifs – A Perspective from Functional Programming

#91

Earlier quoted context omitted.

A church encoded boolean is precisely isomorphic to every language's standard booleans (modulo strictness, perhaps) and doesn't offer any benefits; you're still forking the program based on the information content of a single bit. Let's take the following function invocation, which can be expressed with Boolean literals or Church encoded booleans, I don't care: match true false If you want to determine the significan…

since I'm not a fp expert what about a function like ctx.arc(10, 20, 30, 0, 6.28, false); There's nothing special about boolean. How do you encode all of those above into types in fp so that it's impossible to get them wrong and so they're self documenting? I hope you're not suggesting there be a horizontalFloat type and a verticalFloat type or are you?

I'm a big fan of the philosophy that "Every literal in a program is a bug." :)

But I know what you're getting at! Personally, I'm a fan of programming with units and dimensions, and safely representing the distinction between absolute quantities and relative quantities.

That doesn't mean I'd want an infinite number of "float" values for all possible units and dimensions, however; just a powerful enough type system I can give myself some help at compile-time for properly threading sensical values through my programs.

Re: Destroy All Ifs – A Perspective from Functional Programming

#92
post #5

Define true as a lambda taking two lazy values that returns the first, and false as one that returns the second, and you can turn all booleans into lambdas with no increase in code clarity. The straw man in the post - talking about a case-sensitive matcher that selectively called one of two different functions based on a boolean - is indeed trivially converted into calling a single function passed as an argument, but…

>> you want to change the mechanism of comparison (perhaps introduce locale sensitive comparison) I couldn't agree more, and this is why I think most FP programs are about as intellectual stimulating as `std::min_element`

How does using if statements make it easier to introduce locale sensitive computation? A locale should be represented in the arguments or as a transformation, very similar to what the article is doing.

Re: Destroy All Ifs – A Perspective from Functional Programming

#93

Earlier quoted context omitted.

since I'm not a fp expert what about a function like ctx.arc(10, 20, 30, 0, 6.28, false); There's nothing special about boolean. How do you encode all of those above into types in fp so that it's impossible to get them wrong and so they're self documenting? I hope you're not suggesting there be a horizontalFloat type and a verticalFloat type or are you?

How about keyword parameters... ctx.arc(center=Point(10,20), radius=30, beginAngle=0, endAngle=6.28, Clockwise); ...and don't forget about units of measurement/dimensional analysis. https://stackoverflow.com/questions/107243/are-units-of-meas... ctx.arc(center=Point(10cm,20cm), radius=30mm, beginAngle=0rad, endAngle=6.28rad, Clockwise);

That helps quite a lot, although for several, it's more programming-by-name than programming-by-semantics.

I'd like to be able to say the end angle has to be less than the start angle, that the unit has to be radians (AKA unit-less :), the unit of radius & that negative values are sensical, and so forth; and have all these properties checked by a compiler.

Which I can do in some modern languages, surprisingly. :)

Re: Destroy All Ifs – A Perspective from Functional Programming

#94
post #82

I'm surprised that the article and none of the comments so far mentioned the "Expression Problem": http://c2.com/cgi/wiki?ExpressionProblem Basically, if you structure the control flow in object oriented style (or church encoding...) then its easy to extend your program with new "classes" but if you want to add a new methods then you must go back and rewrite all your classes. On the other hand, if you use if-statemen…

FP and particularly the Haskell community is very aware of the expression problem and you can find many blog posts and papers on solutions.

Re: Destroy All Ifs – A Perspective from Functional Programming

#95
post #88

Earlier quoted context omitted.

Indeed, that's the whole point of inversion of control, is pulling the control out of the caller and into the callee. That's the primary reasoning benefit of functional programming.

I see no benefit to that. It makes more work for the caller. I want that function to do something for me and I want the leadt amount of unnecessary work on my side. Just like a good boss who delegates.

That's why not everyone's a functional programmer. :)

Re: Destroy All Ifs – A Perspective from Functional Programming

#96
post #82

I'm surprised that the article and none of the comments so far mentioned the "Expression Problem": http://c2.com/cgi/wiki?ExpressionProblem Basically, if you structure the control flow in object oriented style (or church encoding...) then its easy to extend your program with new "classes" but if you want to add a new methods then you must go back and rewrite all your classes. On the other hand, if you use if-statemen…

Another alternative is "table-oriented programming", where you define the "classes" and "methods" as an m-by-n structure of code pointers; to add either "methods" or "classes", you would just add a new row/column to the table along with the appropriate code definitions.

and because "expression problem" is not a very catchy name.

It's also not particularly descriptive either, but the page mentions that it's a form of "cross-cutting concern", to which the table-oriented approach basically says "do not explicitly separate the concerns."

(More discussion and an article on that approach here: https://news.ycombinator.com/item?id=9406815 )

As a bit of a fun fact, doing table-oriented stuff in C is one of the few actual uses for a triple-indirection. :-)

Re: Destroy All Ifs – A Perspective from Functional Programming

#97

This is the starter code: publish :: Bool -> IO () publish isDryRun = if isDryRun then do _ This would be nicer if you could do multiple functions with pattern matching. In Elixir this would be: @spec publish(boolean) :: any def publish(true = _isDryRun) do _ = unsafePreparePackage dryRunOptions IO.puts "Dry run completed, no errors." end def publish(false = _isDryRun) do pkg = unsafePreparePackage defaultPublishOpti…

Pattern matching is just as explicit as an if loop. In languages that implement it for null values, it is just as explicit as typing "if (foo == null)" in an imperative language. You have to think about it, and type just as much code to deal with it, as you would in a language without pattern matching. The only upside to pattern matching that I can see is that you are forced by the compiler to match all possible inpu…

Another advantage of pattern matching is extensibility.

Suppose you wish to add a new branch case. Under the traditional if/else (or switch) model, you'd need to modify the function containing the if statements. With pattern matching, you simply introduce a new function; it decentralizes the change and acts as a sort of simple, intuitive polymorphism.

Re: Destroy All Ifs – A Perspective from Functional Programming

#99
post #5

Define true as a lambda taking two lazy values that returns the first, and false as one that returns the second, and you can turn all booleans into lambdas with no increase in code clarity. The straw man in the post - talking about a case-sensitive matcher that selectively called one of two different functions based on a boolean - is indeed trivially converted into calling a single function passed as an argument, but…

Will you marry me?

Re: Destroy All Ifs – A Perspective from Functional Programming

#100
post #76

Earlier quoted context omitted.

The annoying part there is the repeated "|x| x.". Rust should have syntax to reference a method of an object, instead of having to write a wrapper. So it'd look like .map_err(???.to_string()).

The method whose to_string method you want to reference isn't in scope. You need a function that calls the method on the argument it's called with. Why add a feature for this - worse syntax, if you can just use an anonymous function? Rust is already not the simplest of languages, adding further syntax and features of questionable benefit won't make the language any simpler or easier to understand.

Because repeated "|x| x" is a common noise pattern.
Post reply on HN