Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining bind and return

Tags:

haskell

Consider:

x `f` y = x >>= (return . y)

This function f seems very similar to <$> and flip liftM but <$> doesn't seem to work and I'd have to define an infix operator for flip liftM to make it look nice and I'm presuming one already exists?

Is there a function like what I've described and what is it?

like image 791
Clinton Avatar asked May 09 '26 16:05

Clinton


2 Answers

It is flip liftM, but not <$>. It's also almost exactly the same as flip <$>, but the latter is for the Functor typeclass, not Monad. (In the latest standard libraries the relationship between Functor and Monad is not yet reflected in the typeclass hierarchy, but it will be).

If you want to find where this is defined, you go to FP Complete's Hoogle, enter the type you are looking for

Functor f => f a -> (a -> b) -> f b

and discover it is defined in lens.

like image 197
Tom Ellis Avatar answered May 11 '26 10:05

Tom Ellis


Your function

x `f` y = x >>= (return . y)

is equivalent to flip fmap, so if you don't mind swapping the order, you can import Data.Functor, define fmap and write it as

y <$> x

(There's no need to wait for Functor to be a superclass of Monad; you can go ahead today and define it.)

This has nice precedence so you can write stuff like

munge = Just . remove bits . add things <$> operation 1 
            >>= increase something <$> operation 2

instead of

munge' = do
     thing1 <- operation 1
     let thing2 = Just . remove bits. add things $ thing1
     thing3 <- operation 2
     return . increase something $ thing3

but even nicer, if you import Control.Applicative instead (which also exports <$>), you can combine multiple things, for example:

addLine = (+) <$> readLine <*> readLine >>= print

instead of

addLine' = do
    one <- readLine
    two <- readLine
    print (one + two)

Future-proofing your code

If the Functor-Applicative-proposal goes ahead, you'll have to make all your Monads Applicatives (and hence Functors). You may as well start now.

If your Monad isn't already an Applicative, you can define pure = return and

mf <*> mx = do
   f <- mf
   x <- mx
   return (f x)

If it's not a Functor, you can define

fmap f mx = do
   x <- mx
   return (f x)

The proposal suggests using (<*>) = ap and fmap = liftM, both from Control.Monad, but the definitions above are easy too, and you may well find it even easier in your own Monad.

like image 41
AndrewC Avatar answered May 11 '26 10:05

AndrewC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!