pwm
https://www.youtube.com/playlist?list=PLeEpTaU26pQgpMOAJZ-Eq...
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)
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). 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.Side note: I also think that weaving logical inference and llms together into a virtuous cycle is an interesting topic to explore.
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).
Depends on the industry. The one I work in audit trail is a well-defined and mandatory business concern.
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?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)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) -> Constraint 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).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.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)"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."