Is it Functor or Monad?

I implemented my own Promise framework in C # and wanted to test the concept in Haskell, so after some serious brain training (still very new to this) I produced

data Promise fa = PendingPromise f | ResolvedPromise a | BrokenPromise deriving( Show ) class Future p where later :: (b -> c) -> p (a -> b) b -> p (a -> c) c resolve :: p (a -> b) a -> a -> p (a -> b) b instance Future Promise where later g (PendingPromise f) = PendingPromise (g . f) later g (ResolvedPromise a) = ResolvedPromise (ga) resolve (PendingPromise f) a = ResolvedPromise (fa) 

Finding out how to write this Promise fa data type was a real pain.

In any case, the later method seems to be a kind of applicative functor, and Promises - monads. Is it possible to make a Promise instance of some class and get this functionality instead of implementing my own Future class?


Edit Thanks to @bheklilr, the later function turned out to be fmap masked with a slight data type override

 data Promise ab = PendingPromise (a -> b) | ResolvedPromise b | BrokenPromise instance Functor (Promise c) where fmap f (PendingPromise g) = PendingPromise (f . g) fmap f (ResolvedPromise a) = ResolvedPromise (fa) fmap f BrokenPromise = BrokenPromise 

Knowing that (Promise a) is a Functor, it is easier to understand why Monad.

+6
source share
3 answers

Yes, this is a monad. The easiest way to see this is to watch Promise fa ≅ Maybe (Either fa) , which is why it is also isomorphic to the equivalent of a transformer, which has an already tested standard copy of the monad.

 type Promise' f = ErrorT f Maybe promise2Trafo :: Promise fa -> Promise' fa promise2Trafo (PendingPromise f) = ErrorT . Just $ Left f promise2Trafo (ResolvedPromise a) = ErrorT . Just $ Right a promise2Trafo BrokenPromise = ErrorT Nothing trafo2Promise :: Promise' fa -> Promise fa trafo2Promise = ... -- straightforward inverse of `promise2Trafo` instance Applicative Promise where pure = trafo2Promise . pure fp <*> xp = trafo2Promise $ promise2Trafo fp <*> promise2Trafo xp 

etc.

+9
source

What you need to do is try to implement an instance for Functor and check if it complies with the Functor Laws . Start with an instance:

 instance Functor (Promise f) where fmap f (PendingPromise g) = PendingPromise g fmap f (ResolvedPromise a) = ResolvedPromise (fa) fmap f BrokenPromise = BrokenPromise 

Does this comply with the Functor Laws? Since the cases for PendingPromise and BrokenPromise are always identical, I will exclude them for brevity:

 -- fmap id = id fmap id (ResolvedPromise a) = ResolvedPromise (id a) = ResolvedPromise a -- fmap (f . g) = fmap f . fmap g fmap (f . g) (ResolvedPromise a) = ResolvedPromise (f (ga)) fmap f (fmap g (ResolvedPromise a)) = fmap f (ResolvedPromise (ga)) = ResolvedPromise (f (ga)) 

So yes, it complies with the laws of Functor.

Next, see if you can write Applicative and Monad instances and prove that they comply with the relevant laws. If you can write an instance that does, then your data type is Monad , regardless of the Future class.

+6
source

Here is the last code I came across if someone is using it. The promise is an instance of the Functor class, which was a question, but also implements the Future class, which can solve the promise, maybe get its value and make a new promise.

 data Promise ab = Pending (a -> b) | Resolved b | Broken class Future p where resolve :: pab -> a -> pab getValue :: pab -> Maybe b makePromise :: paa instance Future Promise where resolve (Pending f) a = Resolved (fa) resolve (Resolved a) _ = Resolved a resolve Broken _ = Broken getValue (Resolved a) = Just a getValue (Pending _) = Nothing getValue Broken = Nothing makePromise = Pending id instance Functor (Promise a) where fmap f (Pending g) = Pending (f . g) fmap f (Resolved a) = Resolved (fa) fmap f Broken = Broken 
0
source

Source: https://habr.com/ru/post/969921/


All Articles