
Functional architecture is Ports and Adapters (2016) - mpweiher
http://blog.ploeh.dk/2016/03/18/functional-architecture-is-ports-and-adapters/
======
wz1000
Interestingly, if you rewrite the function with a more general type such as

    
    
        checkCapacity' :: forall f. Functor f => Int -> (ZonedTime -> f Int) -> Reservation -> f (Either Error Reservation)
    

you can guarantee that any effects in the final result only come from the
function you supplied to it, i.e. checkCapacity' cannot add any effects of its
own(Also, it can only "run" the function exactly once).

The type of the arguments of checkCapacity' are also a strict generalisation
of the arguments to

    
    
        checkCapacity :: Int -> (ZonedTime -> IO Int) -> Reservation -> Either Error Reservation
    

meaning that any valid arguments to checkCapacity are valid for checkCapacity'
as well.

~~~
tome
I think you must mean

    
    
        checkCapacity :: Int -> (ZonedTime -> IO Int) -> Reservation -> IO (Either Error Reservation)

------
charlieflowers
Interesting that the foray into Haskell led him to pass in a _value_ rather
than a function ... which is exactly what "Functional Core, Imperative Shell"
proposes.

(Functional Core, Imperative Shell is often linked with Hexagonal / Onion /
Ports and Adapters. It is a bit more opinionated about using values as
boundaries I believe ... and I think it is right).

EDIT: TFA is a good article, worth reading.

~~~
zinking
functional core & imperative shell / haxagonal / onion / ports & adapters /
DDD I really can't figure out the commonality of these metaphors

~~~
Spearchucker
At it's core all of these things are pretty much new names and some
constraints on existing architectural patterns like service/service interface
(facade), layered design, and service agent/service. They tend to be a bit
divisive in that traditional layers, for example (presentation/business/data)
is seen as a constraint, and layers in onion have no constraint. Detractors of
hexagonal architetcure suggest it implies no more than 6 ports and adaptors,
and so on.

Ultimately none of these patterns matter. The design philosophy that underlies
them (separation of concerns, for example) does. It's something that becomes
self-evident as you progress from junior to senior and beyond. We as an
industry seem to love telling each other how our way is the one true way.

------
ToJans
My Haskell is a bit rusty, but I think the Haskell example could improve A LOT
by using monad transformers or a free monad?

~~~
BoiledCabbage
Wouldn't that make it harder to directly translate back to F# which is his
goal?

I understood the only purpose of writing the Haskell was didactic, and to
improve his F# code. It seems that moving further from constructs in F# would
work against this.

~~~
ToJans
I think that computation expressions would allow him to do the same in F#?

