Swift and Rust have a far more elegant solution. Swift has a pseudo throw / try-catch, while Rust has a Result<> and if you want to throw it up the chain you can use a ? notation instead of cluttering the code with error checking.
It’s not a half-arsed copy, it’s borrowing a limited subset of HKT for a language with very different goals. Haskell can afford a lot of luxuries that Rust can’t.
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
classChainable f a b fb where(?.) :: f a -> (a -> fb) -> f b
instance Functorf=> Chainable f a b b where(?.) = (<&>)
instance Monadm=> 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 Maybes (it works with any functor/monad), and maybe you wouldn’t want it to be. In that case you’d do this
classChainableabfbwhere
(?.) :: Maybea -> (a -> fb) -> MaybebinstanceChainableabbwhere
(?.) = (<&>)
instance Chainable a b (Maybe b) where
(?.) = (>>=)
restricting it to only maybes could also theoretically help type inference.
Swift and Rust have a far more elegant solution. Swift has a pseudo throw / try-catch, while Rust has a Result<> and if you want to throw it up the chain you can use a ? notation instead of cluttering the code with error checking.
Removed by mod
It’s not a half-arsed copy, it’s borrowing a limited subset of HKT for a language with very different goals. Haskell can afford a lot of luxuries that Rust can’t.
Removed by mod
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
Note: Lemmy code blocks don’t play nice with some symbols, specifically < and & in the following code examples
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:A?
that returnsB?
A?
that returnsB
you’d end up with
B?
in either caseSay 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 thisclass 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.
Removed by mod