Можно ли написать этот код без использования нотации?

У меня есть какая-то функция

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

Я хотел бы иметь другую функцию:

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

Можно ли написать foo без использования do нотация? Я думал о чем-то вроде liftA2 но это не сработает.

2 ответа

Решение

Мы можем использовать алгоритмическое преобразование из do-блоков, как описано в отчете Haskell:

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

Но мы можем уменьшить количество лямбда-выражений, опуская y переменная:

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)

Или, как говорит @ М. Аруси, мы можем использовать комбинацию join :: Monad m => m (m a) -> m aа также liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c:

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

Вы также можете использовать следующую схему для bar:

Арити 2

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

Арити 3

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

и так далее.

Мне это нравится, так как его проще расширить, чем жестко liftA2,

Другие вопросы по тегам