This isn’t a language level issue really though, Haskell can be equally ergonomic.
The weird thing about ?.
is that it’s actually overloaded, it can mean:
- call a function on
A?
that returnsB?
- call a function on
A?
that returnsB
you’d end up with B?
in either case
Say you have these functions
toInt :: String -> Maybe Int double :: Int -> Int isValid :: Int -> Maybe Int
and you want to construct the following using these 3 functions
fn :: Maybe String -> Maybe Int
in a Rust-type syntax, you’d call
str?.toInt()?.double()?.isValid()
in Haskell you’d have two different operators here
str >>= toInt <&> double >>= isValid
however you can define this type class
class Chainable f a b fb where (?.) :: f a -> (a -> fb) -> f b instance Functor f => Chainable f a b b where (?.) = (<&>) instance Monad m => Chainable m a b (m b) where (?.) = (>>=)
and then get roughly the same syntax as rust without introducing a new language feature
str ?. toInt ?. double ?. isValid
though this is more general than just Maybe
s (it works with any functor/monad), and maybe you wouldn’t want it to be. In that case you’d do this
class Chainable a b fb where (?.) :: Maybe a -> (a -> fb) -> Maybe b instance Chainable a b b where (?.) = (<&>) instance Chainable a b (Maybe b) where (?.) = (>>=)
restricting it to only maybes could also theoretically help type inference.
arc@lemm.ee 1 year ago
You can say it’s half-arsed if you like, but it’s still vastly more convenient to write than if err != nil all over the place