Is there a predefined way to skip calculations that lead to Nothing?

I have three functions

a :: Int -> Maybe Int ai = if i < 100 then Just i else Nothing b :: Int -> Maybe Int bi = if i < 50 then Just i else Nothing c :: Int -> Maybe Int ci = if i > 0 then Just i else Nothing 

And I want to link them together, so that when the result of one function results in Nothing , the input of that function will be returned instead.

I can achieve this with this function:

 import Data.Maybe (fromMaybe) e :: Int -> [Int -> Maybe Int] -> Int ei [] = i ei (f:fs) = e (fromMaybe i $ fi) fs 

-

 *Main> e 75 [a,b,c] 75 

Is there an existing function, Monad instance, or other way in the base libraries that exhibit this behavior?

+5
source share
3 answers

Expanding my comment above - this approach is not too different from the code published by OP.

First, a -> Maybe a determine how to enable the function a -> Maybe a in a -> a , replacing the input for Nothing .

 totalize :: (a -> Maybe a) -> (a -> a) totalize fx = fromMaybe x (fx) 

Then we use the following: we make each function "total" (which means no- Nothing s), end it as Endo , then we make a list of endomorphisms ( mconcat is a composition in Endo monoid).

 e :: [a -> Maybe a] -> a -> a e = appEndo . mconcat . map (Endo . totalize) 

or even (as suggested below)

 e :: Foldable t => t (a -> Maybe a) -> a -> a e = appEndo . foldMap (Endo . totalize) 
+4
source

Well, you can create a -> a from a -> Maybe a :

 repair :: (a -> Maybe a) -> a -> a repair fx = fromMaybe x (fx) 

Subsequently, you can simply combine (.) And repair :

 andThen :: (a -> Maybe a) -> (a -> Maybe a) -> a -> a andThen fg = repair g . repair f 

But there is no library function for this, since there is no general way to get the value from Monad .

+2
source

Are you looking for a monad?

 *Main> let fx = ax >>= b >>= c >> return x *Main> f 1 Just 1 *Main> f 100 Nothing *Main> 

Then, if the result is Nothing, we can achieve the desired final state with fromMaybe (or just maybe and id , the same thing):

 *Main> let gx = maybe x id (fx) *Main> g 100 100 
0
source

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


All Articles