The combination of two error-enhancing features in Haskell

The task that I gave says the following:

Similarly to mapMaybe, define a function: composeMaybe :: (a-> Maybe b) → (b → Maybe c) → (a-> Maybe c) which consists of two error increasing functions.

Type Perhaps a and the mapMaybe function are encoded as follows:

data Maybe a = Nothing | Just a mapMaybe g Nothing = Nothing mapMaybe g (Just x) = Just (gx) 

I tried using this composition:

 composeMaybe fg = fg 

But it does not compile.

Can someone point me in the right direction?

+4
source share
6 answers

The tool you are looking for already exists. There are two Kleisli composition operators in Control.Monad.

 (>=>) :: Monad m => (a -> mb) -> (b -> mc) -> a -> mc (<=<) :: Monad m => (b -> mc) -> (a -> mb) -> a -> mc 

When m = Perhaps the implementation of composeMaybe will be implemented:

 composeMaybe = (>=>) 

Looking at the definition (>=>) ,

 f >=> g = \x -> fx >>= g 

which you can embed if you want to think about it in your own terms as

 composeMaybe fgx = fx >>= g 

or which can be written in do -sugar as:

 composeMaybe fgx = do y <- fx gy 

In general, I just stick with the use (>=>) , which has good theoretical reasons for the existing one, since it provides the cleanest way to state the laws of the monad.

+7
source

First of all: if something should be gf , not fg , because you need a function that takes the same argument as f and gives the same return value as g. However, this does not work, because the return type f is not equal to the type of the argument g (the return type f has Maybe in it, and the type of the argument g is not).

So what you need to do: Define a function that takes Maybe b as an argument. If this argument is Nothing , it should return Nothing . If the argument is Just b , it should return gb . composeMaybe should return the composition of the function with f.

+6
source

Here's a great tutorial on Haskell monads (and especially the monad , which is used in the first examples).

+5
source
 composeMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c) composeMaybe fg = \x -> 

Since g accepts an argument of type b , but f creates a value of type Maybe b , you must match the result of fx if you want to pass this result to g .

  case fx of Nothing -> ... Just y -> ... 
+4
source

A very similar function already exists - the monadic binding operator, >>= . Its type (for Maybe monad) is Maybe a -> (a -> Maybe b) -> Maybe b , and it is used as follows:

 Just 100 >>= \n -> Just (show n) -- gives Just "100" 

This is not exactly the same as your composeMaybe function, which takes a function that returns Maybe instead of the direct Maybe value for the first argument. But you can write your composeMaybe function very simply with this statement - it's almost as simple as defining a normal layout function, (.) fgx = f (gx) .

+3
source

Notice how close the composeMaybe argument types composeMaybe to what the monadic binding operator wants for the last argument:

 ghci> :t (>>=) (>>=) :: (Monad m) => ma -> (a -> mb) -> mb 

The order of f and g back for composition, so what about a better name?

 thenMaybe :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c) thenMaybe fg = (>>= g) . (>>= f) . return 

Given the following definitions

 times3 x = Just $ x * 3 saferecip x | x == 0 = Nothing | otherwise = Just $ 1 / x 

can, for example,

 ghci> saferecip `thenMaybe` times3 $ 4 Just 0.75 ghci> saferecip `thenMaybe` times3 $ 8 Just 0.375 ghci> saferecip `thenMaybe` times3 $ 0 Nothing ghci> times3 `thenMaybe` saferecip $ 0 Nothing ghci> times3 `thenMaybe` saferecip $ 1 Just 0.3333333333333333 
0
source

All Articles