You can't do it generically though because Rust doesn't support higher-kinded types, which means no fmap. There's a big GH issue to bring HKTs to Rust one day so the Rust community can start writing monad tutorials like "A monad is just a shell exchanging crabs bro what's the problem???"
@Sydney Bean Point is: fn test1() -> Option { let a = may_fail()?; let b = may_also_fail()?; Some(a + b) } is the same as fn test2() -> Option { may_fail().and_then(|a| may_also_fail().map(|b| a + b)) } play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d5e6fa175cdba9bc18b108c98f828124
This is a very nice and elegant solution. However it's a little bit unsatisfactory that it only wraps two functors at a time... is there a way to declare a recursive datatype that fmaps over an arbitray length of composition? A little bit like the free monad
@@SomeMrMindism i don't know what I'm trying to say either. the only recursive datatype I know in Haskell is Tree. Maybe you could do something like the Functor Tree example from learnyouahaskell but instead of left and right branches, just do a right branch. don't know. I'm just learning Haskell.
I know you are partiality joking about Rust developers unwraping everything, but there do exist functor and monadic functions in rust for Option, Result, and other types and should be used along with the try operator when you need use wrapped values (much like do notation).
I'm following allowing in VS Code, and I'm curious why the linter included with the haskell extension is recommending `newtype` instead of `data`. Do you have an opinion Tsoding?
in this case newtype is better because it essentially creates a wrapper for your types which exists only in design time and is stripped in runtime. so by using newtype you aren't creating new entities, just referencing the same types and implementing different interfaces for them
it bothers me soo much that the type signature of is () :: Functor f => (a -> b) -> f a -> f b and not () :: Functor f => f a -> (a -> b) -> f b with the second signature we could've written beautiful code like foo :: Functor a -> Functor b foo x = x func1 func2 func 3 just like the monad >>= operator
"Rust developers must constantly unwrap everything." Uh... we have Option::map and Either::map_ok. Sure, they're not typeclasses, but they're still quite composable.
defining liftA2 instead of () for Compose is much easier and intuitive instance (Applicative f, Applicative g) => Applicative (Compose f g) where pure = Compose . pure . pure liftA2 f (Compose a) (Compose b) = Compose $ (liftA2 . liftA2) f a b
"You still perform double penetration, but you hide it from the user"
- - Tsoding
Tsoding trolling us by asking us to implement the composition of monads 🤣
Tsoding is the king of penetration
And double penetrantion as well
@@nilp0inter2 fmap . fmap so?
I love how you use the word "secret" to make this video more appealing to click on
Sure appealed to me
Rewatching your old videos, and this intro hit as hard as it did 4 years ago :D
"Injecting" things is how we get endofunctors. Truly the mathematical way of doing compositions and metaprogramming.
pun intended?
the bottom of the screen says "Porn Folder: 43.9 GiB"...that's not nearly enough, man.
too smol PepeHands
Well there are a lot of penetrations and double penetrations in the video
Rust values can be mapped. It's pretty easy to implement a functor trait. Unwrap is actually a code smell
You can't do it generically though because Rust doesn't support higher-kinded types, which means no fmap. There's a big GH issue to bring HKTs to Rust one day so the Rust community can start writing monad tutorials like "A monad is just a shell exchanging crabs bro what's the problem???"
it's impossible to implement a functor trait in Rust, as of now.
text version of would be called "apply".
if you're talking about the specific operator I call it the spaceship operator
That might be confused with the spaceship operator in languages like Perl, .
@@variadicism1047 not likely!
"In Rust you unwrap everything"
Oh yeah?
fmap (\x -> x + 1) (Just 5)
is written
Some(5).map(|x| x + 1);
in Rust
no unwrap required.
I dont think he was saying you can't but that devs often don't. I've seen this in other languages like java
@Sydney Bean the question mark operator is just monadic bind in the context of optionals. It performs the exact same function
@Sydney Bean
Point is:
fn test1() -> Option {
let a = may_fail()?;
let b = may_also_fail()?;
Some(a + b)
}
is the same as
fn test2() -> Option {
may_fail().and_then(|a| may_also_fail().map(|b| a + b))
}
play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d5e6fa175cdba9bc18b108c98f828124
@@NikolajLepka how would this look like in Haskell?
@@chaoky the link I posted in the comment has the Haskell versions written in comments
inb4 this gets demonetized for "double penetration"
Ah hell yea so that's how you use it!
How about triple without fmap?
Maybe one on transformers / free monads or effects to help "compose" monads?
This is a very nice and elegant solution. However it's a little bit unsatisfactory that it only wraps two functors at a time... is there a way to declare a recursive datatype that fmaps over an arbitray length of composition? A little bit like the free monad
You could nest the compose. Then the outer compose uses the fmap of the inner one in its fmap, so everything would work automatically.
((+1) ) (map Just [0..4]) gives [Just 1,Just 2,Just 3,Just 4,Just 5]
@@JaycenGiga Yes, but then to get the inner value you'd need to know how long the chain is.
@@kriswright5112 I'm sorry but I don't understand what you're trying to say. You've just switched the two functors
@@SomeMrMindism i don't know what I'm trying to say either. the only recursive datatype I know in Haskell is Tree. Maybe you could do something like the Functor Tree example from learnyouahaskell but instead of left and right branches, just do a right branch. don't know. I'm just learning Haskell.
2:31 "b-but alexey w-we haven't even been on a date yet..."
why not newtype Compose , bljat'?!
Thank you....
What the text editor are you using? It looks so cool.
That's emacs
I know you are partiality joking about Rust developers unwraping everything, but there do exist functor and monadic functions in rust for Option, Result, and other types and should be used along with the try operator when you need use wrapped values (much like do notation).
Thanks for another great video, maybe a tut about haskell memoization for us mere mortals. This mortal is struggling.
Another great tutorial. The only thing; my brain hurts.
20:13 g that contains b, that just made so much things click!
2:26 succ
If this channel needs one thing, it's regular scheduling
See tsoding daily
I know that you wrote it 3 years before
I'm following allowing in VS Code, and I'm curious why the linter included with the haskell extension is recommending `newtype` instead of `data`. Do you have an opinion Tsoding?
in this case newtype is better because it essentially creates a wrapper for your types which exists only in design time and is stripped in runtime. so by using newtype you aren't creating new entities, just referencing the same types and implementing different interfaces for them
it bothers me soo much that the type signature of
is
() :: Functor f => (a -> b) -> f a -> f b
and not
() :: Functor f => f a -> (a -> b) -> f b
with the second signature we could've written beautiful code like
foo :: Functor a -> Functor b
foo x = x
func1
func2
func 3
just like the monad >>= operator
you can use for exactly that. is defined that way to be similar to $. is also similar to &.
is defined in Data.Functor, & is defined in Data.Function
You can (and should) use map on Option in Rust
...Next train to "JSON Parser" station departs in 26 minutes 44 seconds from "Tsoding Channel" platform...
Yay! Haskell it is!
"Rust developers must constantly unwrap everything."
Uh... we have Option::map and Either::map_ok. Sure, they're not typeclasses, but they're still quite composable.
nice. glad i subscribed half a year ago
yay i wanna be on the list of people at the end
That intro tho...
amazing intro 😂
That was great, thank you! Now, I thought `bind` was *exactly* a composition of monads? The comments here suggest otherwise.
I thought monads do not compose in general.. edit ok just saw the description of the vid lol
this guy is the best
Monads don't compose lol
damn - I really want to share this with my co-workers but it's clearly NSFW
fmap = fmap . fmap
pure = pure . pure
😜
liftA2 = liftA2 . liftA2
defining liftA2 instead of () for Compose is much easier and intuitive
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure = Compose . pure . pure
liftA2 f (Compose a) (Compose b) = Compose $ (liftA2 . liftA2) f a b