Search code examples
haskelllinked-listmonadsdo-notation

Is it possible write this code without using do notation?


I have some function

bar :: MyType -> MyType -> [MyType]

I would like to have another function:

foo :: [MyType] -> [MyType]
foo xs = do x <- xs
            y <- xs
            bar x y

Is it possible to write foo without using the do notation? I was thinking about something like liftA2 but that won't work.


Solution

  • we can use the algorithmic conversion from do-blocks, as described in the Haskell report:

    foo :: [MType] -> [MType]
    foo xs = xs >>= \x -> xs >>= \y -> bar x y
    

    But we can reduce the amount of lambda-expressions, by omitting the y variable:

    foo :: [MType] -> [MType]
    foo xs = xs >>= \x -> xs >>= bar x
    

    and we can omit the x variable as well, by writing \x -> xs >>= bar x as (xs >>=) . bar

    foo :: [MType] -> [MType]
    foo xs = xs >>= ((xs >>=) . bar)
    

    Or like @M.Aroosi says, we can use a combination of join :: Monad m => m (m a) -> m a and liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c:

    foo :: [MType] -> [MType]
    foo xs = join (liftA2 bar xs xs)