Sic transit gloria mundi
HN user
pwm
I'm assuming a lot is coming from companies where there's fomo that if you don't use the latest and greatest tooling, your competitors will and you'll be left behind.
Artificial | Full-time | Remote (Europe) | London | https://artificial.io/careers/
We are building the specialty (re)insurance landscape of the future. Our technology is revolutionising how brokers and carriers operate in complex markets.
Site Reliability Engineer: https://artificiallabsltd.teamtailor.com/jobs/5882832-site-r... (Fully remote)
Design Engineer: https://artificiallabsltd.teamtailor.com/jobs/5728149-design... (Fully remote)
Solutions Engineer: https://artificiallabsltd.teamtailor.com/jobs/5441617-soluti... (Hybrid Onsite)
Thanks for this! It's always nice to learn about the origins of things. I was around when they were called "self"/"super", but I never made the connection to OOP.
I would love to read more about all this, especially how overlays came from "object-oriented" programming. To me, the interesting part is their self-referential nature, for which lazy eval is indeed a great fit!
For anyone interested, this is how I'd illustrate Nix's overlays in Haskell (I know I know, I'm using one obscure lang to explain another...):
data Attr a = Leaf a | Node (AttrSet a)
deriving stock (Show, Functor)
newtype AttrSet a = AttrSet (HashMap Text (Attr a))
deriving stock (Show, Functor)
deriving newtype (Semigroup, Monoid)
type Overlay a = AttrSet a -> AttrSet a -> AttrSet a
apply :: forall a. [Overlay a] -> AttrSet a -> AttrSet a
apply overlays attrSet = fix go
where
go :: AttrSet a -> AttrSet a
go final =
let fs = map (\overlay -> overlay final) overlays
in foldr (\f as -> f as <> as) attrSet fs
Which uses fix to tie the knot, so that each overlay has access to the final result of applying all overlays. To illustrate, if we do: find :: AttrSet a -> Text -> Maybe (Attr a)
find (AttrSet m) k = HMap.lookup k m
set :: AttrSet a -> Text -> Attr a -> AttrSet a
set (AttrSet m) k v = AttrSet $ HMap.insert k v m
overlayed =
apply
[ \final prev -> set prev "a" $ maybe (Leaf 0) (fmap (* 2)) (find final "b"),
\_final prev -> set prev "b" $ Leaf 2
]
(AttrSet $ HMap.fromList [("a", Leaf 1), ("b", Leaf 1)])
we get: λ overlayed
AttrSet (fromList [("a",Leaf 4),("b",Leaf 2)])
Note that "a" is 4, not 2. Even though the "a = 2 * b" overlay was applied before the "b = 2" overlay, it had access to the final value of "b." The order of overlays still matters (it's right-to-left in my example tnx for foldr). For example, if I were to add another "b = 3" overlay in the middle, then "a" would be 6, not 4 (and if I add it to the end instead then "a" would stay 4).TIL there's a vouche feature. Thanks!
One thing I've discovered and utilised from a relatively early age was synergising the difference in how my conscious and subconscious processes information. It's really just the usual advice of "when stuck, go for a walk" but in my experience it's a very useful tool when done mindfully.
Apologies for my meta-meta-comment :) I've been writing code for ~30 years in various languages, and today my brain can't compute how people find any syntax other than this more intuitive:
data Thing
= ThingA Int
| ThingB String Bool
| ThingC
To me, the above syntax takes away all the noise and just states what needs to be stated.Very cool! We developed similar technologies for a very different domain (insurance automation).
Side note: I also think that weaving logical inference and llms together into a virtuous cycle is an interesting topic to explore.
I know next to nothing about these but a friend of mine was grumbling the other day about why can't he just use his electric car's huge battery to power his house. It sounded like a great thing? During the day his solar panels charge his car and at night it could power the house (to some extent). I remember him saying something like this is being trialled in Japan maybe? Anyone knows more about this?
I think for the last 10 years of my career at BigTech, I can't possibly quantify my impact in numeric terms because they were such small pieces of gargantuan projects.
Honestly, this would make me depressed rather quickly. I can't imagine not knowing/experiencing my impact via the work I do. Maybe it is one of the personality differences between people choosing to work for startups/scaleups vs. big tech (no judgement either direction, just my conjecture).
I know a lot of people dislike bitcoin here but I'm wondering (with the huge assumption that its value stabilises over time) would it not actually be a better solution? Not just from an obvious logistical but also from an environmental perspective? I'd imagine gold mining to be much more destructive (both to nature and to human life).
Not sure if you’d win that bet or not but my anecdata is that me and probably the majority of my social circle spend near-0 on alcohol and sweets. They/we buy good quality food and that became mighty expensive.
Pretty much yep. I'd also say it boils down to age which tends to correlate with having a family and also better WFH conditions. When I was young, single, living in a small apartment going into a nice office was great. Nowadays I'm older, have a wife, a kid, a house with a nice garden office. I still love and enthusiastic about what i do but thanks to the internet i can do it from the comfort of my own place.
At our company we came to the same conclusion. We have a DSL that is essentially a programmable schema to describe the shape of the data (more specifically a contract) you want to capture as well as how answers and decisions are derived from it. The only hard validation we have are types, eg. you can't put letters in a box that captures a number type. Other than types the rest is soft-validation which means that you can input anything, even if it is partial or not quite correct, and the system will do its best with what it has. In tandem, at any point in time you can ask the system to tell you what is missing and/or incorrect. All this then affects the lifecycle of the information, ie. you can't move past certain checkpoints in the workflow if the information is not in the required shape. In the context of a medical software imagine you can fill in just the things that will get you back meaningful answers to help you treat someone and you can deal with the rest after to make the case complete.
It feels like there is an article like this every other week. They reflect the same generic view which is broadly true yet I think is not very useful as an advice. In a highly creative field like software competitive advantage often outweighs comparative disadvantage. In other words it might very well be the case that a company that takes a chance on something unusual with a higher opportunity cost will outcompete competitors. How to make the "right" choice of unusual is where the interesting questions lie but that is highly context-dependent and can't easily be generalised into a blog post.
Likewise, it's not an audit trail it's a "history" or "undo".
Depends on the industry. The one I work in audit trail is a well-defined and mandatory business concern.
forever being assaulted by Result<>. Without .unwrap() your progress would be destroyed as you'd have to immediately deal with every unhappy path.
I don't know much about Rust but eg. in Haskell you run a Result-returning computation in its monadic context where success continuation/failure propagation is taken care of by the underlying machinery (ie. the implementation of bind), eg.:
f :: Either Error Stuff
f = do
foo <- getFoo ...
bar <- getBar ...
...
Does Rust have something similar?Not OP but they meant https://hackage.haskell.org/package/base-4.16.1.0/docs/Data-...
As you have the normal map function for Functors (using Haskell):
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
you can have bimap for Bifunctors: > :t bimap
bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
which specialised to pairs is: > :t bimap @(,)
bimap @(,) :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)So in essence I could think of types as functions (possibly nullary) from types to types?
Type constructors, yes. In Haskell the type of type constructors are called kinds:
λ> :kind Bool
Bool :: Type
λ> :kind Maybe
Maybe :: Type -> Type
λ> :kind Maybe Int
Maybe Int :: Type
λ> :kind Either
Either :: Type -> Type -> Type
λ> :kind Eq
Eq :: Type -> Constraint
λ> :kind Functor
Functor :: (Type -> Type) -> ConstraintIt's just semantics.
data Bool = False | True
data Maybe a = Nothing | Just a
Bool is a nullary type constructor or simply type. False and True are nullary data constructors or simply constants. Maybe is an unary type constructor taking one parameter to construct a fully saturated type (eg. Maybe Int), but calling it a "Maybe type" is ok, no crazy ambiguity. Nothing is a constant and Just is an unary data constructor taking one parameter to construct fully saturated data (eg. Just 1).Sum types are one of those things missing from most mainstream languages that people don't even realise that they are deprived of something fundamental. They naturally complement product types that are ubiquitous in most/all languages.
In the context of Haskell "ad-hoc" means ad-hoc polymorphism.
See https://wiki.haskell.org/Polymorphism for details on parametric (ie. unconstrained) vs. ad-hoc (ie. constrained) polymorphism. In short the difference is that ad-hoc is parametric + one or more type class constraints. Eg. in:
λ> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
the type variables a and b are unconstrained while f is constrained by the Functor type class.For readers wondering why this is, there are a few things at play here. I preface my explanation by saying that the benefit of type classes vastly outweigh issues like the above example. Also if I put the above example in my work project I immediately get a warning about the exact issue, so it's not like it is a foot gun or anything like that. Anyhow:
0. Integer is arbitrary precision while Int is bounded, machine dependent (eg. 32 or 64 bit). They are both instances of the Num type class as well as the Integral type class as we'll see later.
1. Numbers without explicit type signatures are overloaded (aka. constraint polymorphic):
λ> :t 1
1 :: Num p => p
where p can be any type that has a Num constraint, like Integer or Int.2. As per https://www.haskell.org/onlinereport/decls.html#sect4.3.4 we have
default (Integer, Double)
as concrete types for numbers to default to in expressions without explicit type signatures to guide inference.3. The type of the list index operator is:
λ> :t (!!)
(!!) :: [a] -> Int -> a
where the index is a concrete Int type.Right, so in the above example if we check the type of 7^7^7`mod`5`mod`2
λ> :t 7^7^7`mod`5`mod`2
(7^7^7`mod`5`mod`2) :: Integral a => a
it is still overloaded (Integral), ie. can be either Integer or Int. Now in the first case there's nothing to concretise the type thus we are defaulting to Integer as per the defaulting rule. In the second case the usage of (!!) concretise the type to an Int. As 7^7^7 is big it does not fit in an Int (overflows). Compare: λ> 7^7^7`mod`5 :: Integer
3
λ> 7^7^7`mod`5 :: Int
2
The mystery is now solved. Side note: if we do default ()
to prevent GHC defaulting we'll get a type error and we will be forced to specific a type. We can also say: λ> ( (7^7^7`mod`5`mod`2)==1, [False,True]!!fromInteger((7^7^7`mod`5`mod`2)) )
(True,True)Just to preserve the full message :)
"Something’s gone awry and we’re having trouble loading your workspace. Sorry we can’t be more specific - this is one of those cases where we don’t know what’s gone wrong either. A restart of Slack might help, and you can always contact us."
Sure, I don't disagree but (to me anyway) it's important to point out the difference between reality vs. our potential intake from it. The blind men and the elephant parable applies.
We do experience reality directly: our nerve endings do.
Depending on how you define "reality" we only experience a tiny subset of it. We can only see/hear/touch/smell/taste a very restricted universe, only what our "antennas" can detect. In fact I would argue that we experience close to 0% of all of reality. On top of this extremely restricted input our processing of it is imperfect which means some of what we experience has nothing to do with reality.
Why do you feel that OP is looking down on you? That's not at all what I took away from his post.