是否可以在不使用 do 符号的情况下编写此代码?

Is it possible write this code without using do notation?

我有一些功能

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

我想要另一个功能:

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

是否可以不使用 do 表示法而写成 foo?我在考虑 liftA2 之类的东西,但那行不通。

我们可以使用 do 块的算法转换,如 Haskell report:

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

但是我们可以通过省略 y 变量来减少 lambda 表达式的数量:

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

我们也可以省略 x 变量,将 \x -> xs >>= bar x 写成 (xs >>=) . bar

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

或喜欢 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)

您也可以使用以下模式来改变 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

等等。

我喜欢这个,因为它比硬编码更容易扩展 liftA2