user1747134
user1747134

Reputation: 2482

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.

Upvotes: 1

Views: 118

Answers (2)

Camsbury
Camsbury

Reputation: 121

You may also use the following pattern for varying arities for bar:

Arity 2

-- bar :: [MType] -> [MType]
foo :: [MType] -> [MType]
foo xs = join $ bar <$> xs <*> xs

Arity 3

-- bar :: [MType] -> [MType] -> [MType]
foo :: [MType] -> [MType]
foo xs = join $ bar <$> xs <*> xs <*> xs

and so on.

I like this as it is easier to extend than the hardcoded liftA2.

Upvotes: 2

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477437

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)

Upvotes: 7

Related Questions