函数式编程课程总结
Functional Programming Lessons Conclusion

原始链接: https://jerf.org/iri/post/2025/fp_lessons_conclusion/

作者认为,虽然函数式编程(FP)提供了宝贵的原则,但在命令式语言中微观层面教条式地应用它们可能会适得其反。过分专注于用map和reduce替换循环,而不解决高层次的架构问题,只会带来微小的收益,甚至倒退。 作者主张采取一种务实的方法,关注在命令式环境中中等规模的FP原则应用。这包括管理状态变化流程,简化架构,协调接口,利用更强大的类型系统,以及防止无效对象的创建。这些高层次的考虑比微观优化更有益。 纯粹的FP提供了优势,特别是不可变性和可靠的类型系统,但全面采用它可能会限制其他潜在的解决方案。作者建议采取组合策略,使用多种“80/20”解决方案,而不是追求单一的、代价高昂的“100/100”解决方案。虽然FP语言在特定场景中可能是理想的,但现实世界中的各种问题往往受益于更广泛的工具集。关键在于汲取FP的宝贵经验,而不屈服于教条式的应用。

Hacker News 最新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 函数式编程课程总结 (jerf.org) 4 分,来自 speckx,1小时前 | 隐藏 | 过去 | 收藏 | 讨论 加入我们,参加 6 月 16-17 日在旧金山举办的 AI 初创公司学校! 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系我们 搜索:
相关文章
  • (评论) 2023-12-09
  • 组件简洁性 2025-03-21
  • (评论) 2023-11-06
  • 解析,不验证 (2019) 2024-07-23
  • (评论) 2024-08-04

  • 原文

    As many others observe as well, one of the major reasons to write is to firm up ideas in one’s own head. Serializing an idea out into English words is still no guarantee one understands it deeply, but it is great progress over a very fuzzy idea that has never been fleshed out at all.

    I’ve known for a long time I wanted to sit down and write this out. But I had no idea how many principles I’ve either drawn out from my times with functional languages, or had sharpened by them forcing me on to certain paths that perhaps I would have walked eventually, in bits and pieces, but functional programming forced upon me in toto.

    And it wasn’t until I’d written several of these posts that I noticed the recurring theme of scale, that functional programming principles are best brought in to imperative languages at the medium scale rather than the micro scale. I find this insight to have been almost worth the writing on its own.

    I arranged these points roughly in order from least offensive to most offensive, so it’s possible that you arrive here thinking I do not like functional programming. But consider how much I have drawn from it. This is a good thing. I like it.

    What I do not like is what I consider the surface level application of the lessons of functional programming. I do not like people obsessing about the micro-scale of functional programming, often to the point they actually harm their own code bases, while at the same time writing higher-level structures indistinguishable from the rest of the imperative world.

    If all you’ve done is walk through your program and change all your for loops into maps and reduces, but your high-level architecture is still a confused mess with no discernable boundaries or structure… at best you’re got a marginal gain, and most likely, you’ve taken a step backwards!

    If you are lucky enough to work in a domain where you can use high-end functional programming languages, by all means, adopt the relevant idioms wholesale.

    But if you are not, I encourage to worry less about whether you should replace a for loop with a map and which library offers the best map call and more about things like:

    • How does mutation flow through this program? Can I use mutation flow fences in my architecture to isolate parts effectively?
    • How complicated are the parts in my architecture? How can I simplify their requirements?
    • Can I harmonize what seem to be disparate types of things into single interfaces that I can then build on?
    • Can I prevent strings and ints from flowing around my program naked? How can I derive synergistic benefits from stronger types?
    • Even if I’m not using Haskell or a proof language, how can I use the local type system to prevent bugs from existing in the first place? Even in fully dynamic languages there are things that can be done.
    • How can I prevent invalid objects from being created in the first place, thus solving all problems created by invalid objects? I know it can be done because functional languages do it.

    And the other sorts of things I have described in this essay series. These are far more important then questions like whether these ten lines of code are formatted this way or that way, much more consequential in the long term.

    So often in engineering we have the “80/20” option; 80% of the benefit for 20% of the effort. The temptation of a purist is to sneer at an 80/20 for not trying hard enough when clearly the correct answer is 100/100, and anything less is failing to get all the benefits that are possible.

    Most of the time, as one puts more effort in, the benefit obtained rather smoothly increases, usually quickly at the beginning and then asymptotically approaching 100% towards the end. It is unusual for there to be a sudden spike in utility at 100%, which makes the cost/benefits analysis of 100/100 often quite unappealing.

    However, I fully agree that functional programming is indeed one of those exceptions! The difference between a programming language in which values are always immutable and one in which values are almost always immutable is quite substantial. In one, you can build on that guarantee of total immutability; in the second, you can’t, because it just isn’t quite reliable, and as you scale up, the odds of that “not quite reliable” biting you approach 1. I consider this a characteristic of type systems in general; a type system that you can rely on is vastly more useful than a type system you can almost rely on, and it doesn’t take much “almost” to greatly diminish the utility of a given type system. Even unsafe functionality is generally fenced in by the local type system, and where that is not possible, by language convention.

    So I agree there is value in the 100/100 solution for functional programming.

    If that is the case, then the question looms over programming as a whole, why don’t we all, all the time, just use functional programming languages then?

    The answer to that is an underappreciated cost of the 100/100 approach, which is that it tends to forstall other possible benefits. You spent all your effort getting to that 100%.

    But the pragmatist’s secret, unappreciated by the purist, is that the pragmatist does not have just one 80/20 solution. Having spent only 20%, the pragmatist also has another 80/20 solution, and another, and another, and another, altogether adding up to 400% worth of solutions.

    … ok, sure, that’s taking the “80/20” numbers too literally, but the general point holds. For the same “cost” you can often buy a lot more with a bunch of 80/20 solutions than one 100/100 solution, or you can buy 2 of them and a 95/60 for the thing you really need. The diverse problems we face in the real world are often better addressed with such a diverse portfolio.

    Not always. There are times and places to go all-in with a certain tool to the exclusion of all else. But those are broadly the exceptions, not the rules. Exceptions a wise engineer does well to be aware of!… but exceptions nonetheless.

    And so, when considered against the at-times bewildering constellations of requirements being made upon our programs, it is often the case that a 100% commitment to a pure functional programming language is a bad choice, for reasons ranging the full spectrum of “technical” to “human”.

    In this it is not unique; 100% pure commitments to any choice can turn out poorly. Those around during the late 1990s to early 2000s probably still carry scars from the XML all the things! of the era. There have been plenty of other examples, and senior engineers who probably shouldn’t be senior engineers are remarkably creative in their ability to come up with dogmatic “100% solutions” to some problem that you’ve never even heard of that will destroy the local code base in time.

    But you don’t have to give up everything you’ve learned. You are not doomed to the outer pit of Imperative Hell just because local engineering considerations preclude a pure functional language. You still have the knowledge and skills you picked up from your foray into the Functional Programming world. You can still apply them. You can still benefit from them.

    But those benefits don’t come from forcing micro-styles on to languages that don’t benefit from them. They come from these medium-scale-and-larger lessons.

    If I have infuriated you, I hope I have at least given you something to think about, and I hope that the process of chewing on these comments benefits you and your programming skills. It isn’t even necessary to agree with me to find your own ideas and principles sharpened, and if that happens, even if you disagree, I will still consider this a success.

    联系我们 contact @ memedata.com