Live data from Hacker News

The general value of typed functional programming lies in leaving no edge cases

np.reddit.com

21–30 of 172 posts

Re: The general value of typed functional programming lies in leaving no edge cases

#21
post #13

Earlier quoted context omitted.

The problem in my domain, games, is the frequent boxing and unboxing of values when using functional iterator interfaces in languages common to the industry, particulalry C#. It just thrashes the heap and forces often too-frequent gc.

I was under the impression that the way C# did generics meant that there was no need to box values. (Unlike Java, which treats all values as objects, even value types.)

C# has value types and many things are value types but certain things are not. Core library interfaces are implemented as with Object enumerator types for example. This causes IList.GetEnumerator() to return a boxed type. Its smart enough to use the value type when it knows it can though, such as List.GetEnumerator().

Lambdas have some allocations. I like LINQ but it can have some allocation as well.

These are all tiny allocations but in a game you'd like to strive for 0 allocations.

Re: The general value of typed functional programming lies in leaving no edge cases

#22
Most languages rely on coding patterns for code safety. This is merely a best practice, usually involves writing multiple lines of code, and is merely a convention.

Functional languages have many of these patterns already encoded into common functions, like map and fold. As functions their correctness can be considered mathematically proven. Would you rather rely on convention or the compiler?

Consider adding on top of functional safety/correctness type safety with a functional language implementing a strong type system, like F#. Sure, F# is only functional first, not purely functional, and probably all type system have some sort of implementation edge issues. For most practical purposes you can consider the added level of type safety imposed by the compiler also to be mathematically provable.

Re: The general value of typed functional programming lies in leaving no edge cases

#23
post #13
post #2

Edge case removed: for i=0 to 10 {print(a[i])} vs for x in a {print(x)} With functional programming it gets even better: a.filter {}.map{print} Pseudo code, of course. I list several “functional“ examples in Swift here: https://github.com/melling/SwiftCookBook/blob/master/functio... Functional programming is also a higher level language. map, reduce,filter, flatten, flapMap, drop, take, zip, ... Learn the concepts in…

The problem in my domain, games, is the frequent boxing and unboxing of values when using functional iterator interfaces in languages common to the industry, particulalry C#. It just thrashes the heap and forces often too-frequent gc.

While it may or may not be optimal for you/your field for other reasons, I believe Rust does iterators in a 0-cost, no allocation way and generally generates code equivalent to or better than a hand-written for loop.

Re: The general value of typed functional programming lies in leaving no edge cases

#24
post #19
post #14

Earlier quoted context omitted.

You can use a functional style in those languages as well. Or do you mean with Rust's borrow checker you have less mutability to worry about?

If you have a Rust enum with Color{Red,Green,Blue), if for some reason you update to Color{Red,Green,Blue,Yellow}, the rustc compiler will force you to manage the new Yellow case wherever you want to "match" a pattern on Color, so overall you have less chance to forget to manage the new case everywhere. This kind of error is not managed by a C or C++ compiler (as far as I know). But from my understanding, this is not…

If you compile with `-Wall` GCC will emit a warning for failing to exhaustively check enum values inside a switch statement

(I don't remember the specific underlying feature flag name, sorry).

EDIT: It's called `-Wswitch`

Re: The general value of typed functional programming lies in leaving no edge cases

#26
post #3

The goal of software development should be about reducing the number of edge cases to the absolute minimum. If a tool makes it easier to keep track of all edge cases, it is bound to encourage developers to write code which contains more edge cases. But fundamentally, it still reduces code quality. Code with more edge cases is less flexible and not good at handling changing requirements. I've seen this over and over i…

I've been translating a personal project (game engine) from a dynamically typed language to a statically typed one. Having to pin down what the types of function parameters are and spell out interfaces for objects has been eye opening. Using a dynamically typed language had made it way too easy to stuff things that didn't really go together down "the same pipes" of the existing object collaborations. I thought I was writing simple code, but it only appeared simple because I wasn't fully aware of the implicit (defined by behavior) types of my dynamic code. Granted the pace re-writing this with a statically typed language has been slow enough that I can't say whether it's a win overall; my point is just that it has revealed edge cases I never considered in the dynamic code. The argument you made that tools can make people lazy - doesn't that apply as well to dynamic typing?

Re: The general value of typed functional programming lies in leaving no edge cases

#27
post #24
post #19

Earlier quoted context omitted.

If you have a Rust enum with Color{Red,Green,Blue), if for some reason you update to Color{Red,Green,Blue,Yellow}, the rustc compiler will force you to manage the new Yellow case wherever you want to "match" a pattern on Color, so overall you have less chance to forget to manage the new case everywhere. This kind of error is not managed by a C or C++ compiler (as far as I know). But from my understanding, this is not…

If you compile with `-Wall` GCC will emit a warning for failing to exhaustively check enum values inside a switch statement (I don't remember the specific underlying feature flag name, sorry). EDIT: It's called `-Wswitch`

Yes, apparently, there is a -Wswitch statement in gcc, which looks quite similar, maybe I have used too old compilers...

> Warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration. (The presence of a default label prevents this warning.) case labels outside the enumeration range also provoke warnings when this option is used (even if there is a default label). This warning is enabled by -Wall.

Re: The general value of typed functional programming lies in leaving no edge cases

#28

Forget the performance or the fancy memory management stuff, this is one of the best things about Rust: it makes you deal with edge cases by default (while allowing you to write code in a largely imperative or functional-lite style). It's why I think it competes for market share with some of what is currently Java/C# and similar languages. A lot of people who use those languages care about correctness, and Rust is bi…

This is also one of the problems with programming with exceptions. You lean on the fact that an exception will be thrown and just propogate up until it finds something, so the normal mindset of an exception-based programmer is to program for the happy-case and only vaguely think about what happens if it goes wrong. I know, I've written a lot of code in this style for many years myself.

In some cases, that's not a problem or it's even the best thing to do. However, you end up writing this way all the time in an exception-based language, which is where the problem arises.

Non-exception based languages tend to throw the problems in your face and make them something you can't ignore. Which is not fun. But it is often what you need.

Re: The general value of typed functional programming lies in leaving no edge cases

#29
post #19
post #14

Earlier quoted context omitted.

You can use a functional style in those languages as well. Or do you mean with Rust's borrow checker you have less mutability to worry about?

If you have a Rust enum with Color{Red,Green,Blue), if for some reason you update to Color{Red,Green,Blue,Yellow}, the rustc compiler will force you to manage the new Yellow case wherever you want to "match" a pattern on Color, so overall you have less chance to forget to manage the new case everywhere. This kind of error is not managed by a C or C++ compiler (as far as I know). But from my understanding, this is not…

This isn't particular of Rust. Nim also forces you to deal with all possible branches of a case statement. I'm pretty sure other languages do so as well.

This is just basic type safety stuff.

Re: The general value of typed functional programming lies in leaving no edge cases

#30
post #2

Edge case removed: for i=0 to 10 {print(a[i])} vs for x in a {print(x)} With functional programming it gets even better: a.filter {}.map{print} Pseudo code, of course. I list several “functional“ examples in Swift here: https://github.com/melling/SwiftCookBook/blob/master/functio... Functional programming is also a higher level language. map, reduce,filter, flatten, flapMap, drop, take, zip, ... Learn the concepts in…

A lot of those concepts were already in Smalltalk.

    a do: [:x|  Transcript print: x ]
    [] = closure 
That is, because Smaltalk was based on Lisp. But the other OO languages removed this concept, but it came back in Scala.
Post reply on HN