Метод упрощения Хаскелла и монады

Как это может закодировать (или в целом, код с многократными исходными данными) может быть уменьшен/упрощен?

do
  sex    <- askSex
  name   <- askName
  sayHello sex name

В этом случае уже очень коротко, но когда это добирается до многократных исходных данных, это выглядит грязным. Есть ли любой способ сделать что-то как:

sayHello askSex askName

?

2
nl ja de
Этот код выглядит совершенно простым мне
добавлено автор Abhinav Sarkar, источник
Как sabauma говорит, используйте liftM2 . It' s абстракция вашего оригинального кода и что вы хотите.
добавлено автор Fixnum, источник
n.b. Более ясно, включаете ли вы , делают с начала-блока.
добавлено автор dave4420, источник
Проверьте функции в Контроль. Монада, определенно liftM2 .
добавлено автор sabauma, источник
Все короче, чем это, скорее всего, будет причудливо. Если бы вы просили много того же самого вида исходных данных, вы могли бы нанести на карту по тем действиям, но не в этом случае.
добавлено автор Sarah, источник

3 ответы

Если вы

import Control.Applicative  -- for <$> and <*>
import Control.Monad        -- for join

можно написать

join $ sayHello <$> askSex <*> askName

Для вашего примера, где вы только приносите два параметра, это не большая победа. Но для большего количества параметров это может сделать код более четким.

join $ doSomething <$> getFirst <*> getSecond <*> getThird <*> getForth
5
добавлено
It' s идиома позора скобки haven' t превратил его в Хаскелла: соединение (|doSomething getFirst getSecond getThird getForth |) был бы намного более хорошим.
добавлено автор dave4420, источник
Ну, there' s всегда quasiquoter
добавлено автор Ben Millwood, источник

Это - прекрасное время для Применимых Функторов:

import Control.Applicative -- at the top of your module before any functions

hello "Male" name = "Hi, " ++ name ++ ", that's a cool name."
hello "Female" name = "Hello, " ++ name ++ ", that's a pretty name."

greet = hello <$> askSex <*> askName >>= putStrLn

Это работает немного как fmap в предыдущих ответах, которые я дал вам сегодня, но для большего числа аргументов, как вы имеют здесь.

Используя функции как мой привет с применимыми функторами помогает вам отделить свой код IO от остальной части кода, который является очень хорошей практикой. Попытайтесь написать привет вместо sayHello каждый раз.

3
добавлено

Annoyingly, hoogle doesn't have an easy answer for this one. This would be called bind2. If it's a function with only one input, then you can use =<<, the infix version of what I'd call bind1.

sayHello =<< askName

Но для многократных исходных данных, мы неудачливые. По любой причине стандарт освобождает, не обеспечивают это:

bind2 :: Monad m => (a -> b -> m c) -> m a -> m b -> m c
bind2 f mx my = do
  x <- mx
  y <- my
  f x y

...

bind2 sayHello askSex askName

Можно, конечно, просто определить его сами.

1
добавлено
Haskell
Haskell
910 участник(ов)

https://combot.org/chat/-1001043143583 Ссылки на полезные ресурсы: https://ruhaskell.org/links.html ;