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

у меня есть функция

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

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

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

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


person user1747134    schedule 06.09.2018    source источник
comment
Все нотации do можно переписать с помощью >>= и return, для этого даже есть специальная функция использования.   -  person Willem Van Onsem    schedule 06.09.2018
comment
Да, технически вы правы. На самом деле я имел в виду, могу ли я переписать его каким-то естественным образом, используя функции из Control.Applicative или Control.Monad и без лямбда-выражений. Для перезаписи >>= обычно требуется много лямбда-выражений.   -  person user1747134    schedule 06.09.2018
comment
думал о чем-то вроде liftA2, но это не сработает. Почему нет?   -  person Mor A.    schedule 06.09.2018
comment
@M.Aroosi: учтите, что bar здесь является монадическим типом, это не return (bar x y), а просто bar x y.   -  person Willem Van Onsem    schedule 06.09.2018
comment
правильно, вы могли бы использовать liftA2 и join хотя.   -  person Mor A.    schedule 06.09.2018
comment
Возможный дубликат Замена do на ››= для сообщения Скотти   -  person AJF    schedule 07.09.2018
comment
Возможный дубликат дешугаринг do-notation для монад   -  person jberryman    schedule 07.09.2018
comment
Для этой функции будет достаточно foo xs = bar <$> xs <*> xs, поскольку x и y не зависят друг от друга. Это то, что вы получите с расширением ApplicativeDo.   -  person chepner    schedule 07.09.2018


Ответы (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)

Или как @M.Aroosi, мы можем использовать комбинацию 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)
person Willem Van Onsem    schedule 06.09.2018

Вы также можете использовать следующий шаблон для изменения арности для 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.

person Camsbury    schedule 07.09.2018