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

时间:2018-09-06 20:36:55

标签: haskell linked-list monads do-notation

我有一些功能

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

我想要另一个功能:

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

是否可以在不使用foo表示法的情况下编写do?我在考虑类似liftA2之类的方法,但这行不通。

2 个答案:

答案 0 :(得分:8)

我们可以使用来自do-block的算法转换,如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)

或者像@M.Aroosi所说,我们可以结合使用join :: Monad m => m (m a) -> m aliftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c

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

答案 1 :(得分:2)

对于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容易扩展。