The infection of my heart and abdomen appears cured, and I am feeling much better. I am awaiting an appointment with urology. It is likely the kidney will need to be removed. The tumour, I am told, is too small to have metastasised. I will have better information once I meet my urologist, but my current guess is that I will be back at work sometime in March.
My thanks to the NHS and to the Western General Hospital for the excellent treatment I have received, and to all my colleagues for their support.
Hi all - I'm working with Luminal, Inc. on a product called Fugue. It has a growing Haskell component and Luminal is looking for people who'd like to work on it.
Fugue is very cool. Its goal is to realize the ideal of 'immutable infrastructure'; if you want to upgrade a server, you don't touch the existing server itself - you put a new one in its place with the required upgrades sitting nicely in place. Immutability is a property that Haskellers know and love.
Broadly, Fugue provides a way to declare and deploy infrastructure that it then manages. It does this in a way that i) does not impact performance negatively, ii) generates desirable security properties, and iii) provides opportunities for cost optimization and savings.
You can check out more about Fugue at https://fugue.it.
Fugue is a pretty interesting project to work on. It encompasses distributed systems, security, prediction, optimization, and operation in adversarial environments. Of particular interest to Haskell folk is a component of Fugue called Ludwig - a declarative, statically-typed DSL that aims to duplicate the Haskell ideal of 'if it compiles, it probably works' for infrastructure. If a Ludwig infrastructure declaration compiles, your infrastructure should 'just work' as expected.
The primary languages used at Luminal are Python and Go, but the Ludwig compiler is written in Haskell, and internal tools written in Haskell are also starting to appear.
If you might be interested in working on Ludwig and Fugue, feel free to check out the official job ad. If you would consider yourself an intermediate+ level Haskeller with some visible open-source contributions/blog content out there or professional Haskell experience under your belt, I'd especially love to hear from you.
Cheers!submitted by jaredtobin
[link] [18 comments]
Summary: Haskell is great for refactoring, thanks to being able to reason about and transform programs with confidence.
I think one of Haskell's strengths as a practical language is that it's easy to refactor, and more importantly, easy to refactor safety. Programs in the real world often accumulate technical debt - code that is shaped more by its history than its current purpose. Refactoring is one way to address that technical debt, making the code simpler, but not changing any meaningful behaviour.
When refactoring, you need to think of which alternative forms of code are equivalent but better. In C++ I've removed unused variables, only to find they were RAII variables, and their mere presence had a semantic effect. In R I've removed redundant if expressions, only to find the apparently pure condition had the effect of coercing a variable and changing its type. In Haskell, it's equally possible to make refactorings that at first glance appear safe but aren't - however, in practice, it happens a lot less. I think there are a few reasons for that:
- Haskell is pure and evaluation strategy is largely unobservable - moving a statement "before" or "after" another lexically is usually safe.
- Refactorings that do go wrong, for example variables that accidentally get moved out of scope or types which are no longer as constrained, usually result in compiler errors.
- The Haskell community cares about semantics and laws. The Monad laws are satisfied by almost all monads, flagrantly breaking those laws is rare.
- Functions like unsafePerformIO, which could harm refactoring, are almost always used behind a suitable pure abstraction.
Note that these reasons are due to both the language, and the conventions of the Haskell community. (Despite these factors, there are a few features that can trip up refactorings, e.g. exceptions, record wildcards, space-leaks.)
To take a very concrete example, today I was faced with the code:f = fromMaybe (not b) . select
if f v == b then opt1 else opt2
At one point the function f was used lots, had a sensible name and nicely abstracted some properties. Now f is used once, the semantics are captured elsewhere, and the code is just unclear. We can refactor this statement, focusing on the condition:f v == b
-- inline f
(fromMaybe (not b) . select) v == b
-- remove brackets and inline (.)
fromMaybe (not b) (select v) == b
-- expand to a case statement
(case select v of Nothing -> not b; Just x -> x) == b
-- push the == down
case select v of Nothing -> not b == b; Just x -> x == b
-- simplify not b == b
case select v of Nothing -> False; Just x -> x == b
-- collapse back up
select v == Just b
And now substitute back in:if select v == Just b then opt1 else opt2
Our code is now much simpler and more direct. Thanks to the guarantees I expect of Haskell programs, I also have a high degree of confidence this code really is equivalent - even if it isn't obvious just looking at beginning and end.