Live data from Hacker News

Modern Functional Programming: The Onion Architecture

degoes.net

21–30 of 100 posts

Re: Modern Functional Programming: The Onion Architecture

#21
post #7

> Free monads permit unlimited introspection and transformation of the structure of your program; Free monads allow minimal specification of each semantic layer, since performance can be optimized via analysis and transformation. That is not true and this overselling of the Free monad is hurting the concept. The Free monad is nothing more than the flatMap/bind operation, specified as a data-structure, much like how a…

Free monads can be inspected "up to the first lambda", which is always at least one operation in, and it's what enables things like purely functional mocking. However, other free structures, such as free applicatives, can be completely introspected:

https://www.youtube.com/watch?v=H28QqxO7Ihc

The point is that free monads allow introspection up to the information-theoretic limit (obviously you can't inspect a program whose structure depend on a runtime value), while transformers do not allow any introspection at all.

Re: Modern Functional Programming: The Onion Architecture

#22
post #6

Earlier quoted context omitted.

The architectural pattern of implementing a program in a language close to the domain and iteratively transforming it into something that can be consumed in an execution environment long predates OO, and is in fact the principle behind compilers. It came out in a different guise under Model Driven Architecture and executable specifications a few years back. It'll pop up again in the future under some other name. The…

> At the center of the application, semantics are encoded using the language of the domain model. Say pg/psql. > Beginning at the center, each layer is translated into one or more languages with lower-level semantics. ORM mapping into Java? > At the outermost layer of the application, the final language is that of the application’s environment — for example, the programming language’s standard library or foreign func…

Only if you can express your domain well in SQL. For most domains you can't, you need a... domain specific language.

Re: Modern Functional Programming: The Onion Architecture

#23
post #6

Earlier quoted context omitted.

The architectural pattern of implementing a program in a language close to the domain and iteratively transforming it into something that can be consumed in an execution environment long predates OO, and is in fact the principle behind compilers. It came out in a different guise under Model Driven Architecture and executable specifications a few years back. It'll pop up again in the future under some other name. The…

> At the center of the application, semantics are encoded using the language of the domain model. Say pg/psql. > Beginning at the center, each layer is translated into one or more languages with lower-level semantics. ORM mapping into Java? > At the outermost layer of the application, the final language is that of the application’s environment — for example, the programming language’s standard library or foreign func…

    > Beginning at the center, each layer is translated into one or more languages with lower-level semantics.
    ORM mapping into Java?
An ORM would not have lower-level semantics would it?

Re: Modern Functional Programming: The Onion Architecture

#24

Gary Bernhardt describes a similar architecture using a "Functional Core, Imperative Shell" in his Boundaries talk[1]. "Purely functional code makes some things easier to understand: because values don't change, you can call functions and know that only their return value matters—they don't change anything outside themselves. But this makes many real-world applications difficult: how do you write to a database, or to…

I was quite disappointed the author chose not to cite Bernhardt's work, as this is pretty clearly derivative of that talk and other work in the community around this design. I'm certain I've heard Hickey talk about it a few years ago as well. Trying to remember where.

I don't think it's derivative. He mentions the onion architecture, which is an older concept. I really liked the way Gary presented the idea, but he wasn't the originator.

Re: Modern Functional Programming: The Onion Architecture

#25
post #19
post #14

Earlier quoted context omitted.

Yeah, the free monad structures involve lots of lambdas. It's not so much that information is "lost", more that you cannot see beyond the next lambda abstraction. From a DSL perspective, it's like you can only inspect the program so far as to know the next statement in the "do" block. To see what the next statement will be, you need to actually evaluate the current one. Instead of free monads, if you want very analyz…

The problem is that applicative functors aren't powerful enough to allow computations that depend on previous results. I suspect what we want is something like free ArrowChoice, but I'm not aware of any work in that direction.

You can still do a lot with applicatives, like parsing context-free languages... and even parsing context-sensitive languages.

https://byorgey.wordpress.com/2012/01/05/parsing-context-sen...

But yeah.

ApplicativeDo might be useful. You would be able to see the static applicative structure as far as the next monadic bind, which lets you do interesting types of optimization, e.g. Haxl.

https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo

https://github.com/facebook/Haxl

Re: Modern Functional Programming: The Onion Architecture

#26
post #15

Earlier quoted context omitted.

At the lowest levels, the pattern can be reversed: you provide a nice functional shell around a little bit of imperative core (e.g. implementing "map" with a loop).

This kind of abstraction layer is really challenging though unless you're totally aware of the extent of your imperative code's side effects.

Isn't this already happening, though, on a low-level (i.e. ASM) ?

Re: Modern Functional Programming: The Onion Architecture

#27

Gary Bernhardt describes a similar architecture using a "Functional Core, Imperative Shell" in his Boundaries talk[1]. "Purely functional code makes some things easier to understand: because values don't change, you can call functions and know that only their return value matters—they don't change anything outside themselves. But this makes many real-world applications difficult: how do you write to a database, or to…

I'd like to use the occasion that I'm really waiting for the video of his talk "Ideology" given at StrangeLoop 2015.

If it helps at all, here's a transcript of that talk: https://github.com/strangeloop/StrangeLoop2015/blob/master/t...

Re: Modern Functional Programming: The Onion Architecture

#28

Earlier quoted context omitted.

This kind of abstraction layer is really challenging though unless you're totally aware of the extent of your imperative code's side effects.

Isn't this already happening, though, on a low-level (i.e. ASM) ?

But the abstraction there is a lot more battle-hardened than your business logic at $COMPANY. Not that compiler bugs never happen, but it's comparatively quite rare.

Re: Modern Functional Programming: The Onion Architecture

#29
Unrelated to functional programming there is Onion Architecture defined by Jeffrey Palermo in 2008 which I find a very nice and simple way to architect/organize a LoB application.

http://jeffreypalermo.com/blog/the-onion-architecture-part-1... http://jeffreypalermo.com/blog/the-onion-architecture-part-2... http://jeffreypalermo.com/blog/the-onion-architecture-part-3... http://jeffreypalermo.com/blog/onion-architecture-part-4-aft...

Re: Modern Functional Programming: The Onion Architecture

#30

Gary Bernhardt describes a similar architecture using a "Functional Core, Imperative Shell" in his Boundaries talk[1]. "Purely functional code makes some things easier to understand: because values don't change, you can call functions and know that only their return value matters—they don't change anything outside themselves. But this makes many real-world applications difficult: how do you write to a database, or to…

I understand the value of referential transparency and how it makes "certain" things easy, but saying that it automatically makes testing functional code easy is a myth. Sometimes it does, sometimes it doesn't.

If you want to stick to referential transparency, you can't use dependency injection: you have to pass all the parameters the function needs. None of these can be implicit or belong to a field on the class since that would mean side effects. The `Reader` monad is not dependency injection, it's dependency passing and it comes with a lot of unpleasant effects on your code.

And because of that, functional code is often very tedious to test. Actually, in my experience, there is a clear tension between code that's referentially transparent and code that's easily testable. In practice, you have to pick one, you can't have both.

Post reply on HN