简体   繁体   中英

Haskell simplification technique and monads

How can this code (or in general, code with multiple inputs) can be reduced/simplified?

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

In this case is very short already, but when it gets to multiple inputs, it looks messy. Is there any way to do something like:

sayHello askSex askName

?

If you

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

you can write

join $ sayHello <$> askSex <*> askName

For your example, where you are only fetching two parameters, this is not a big win. But for a greater number of parameters it can make the code clearer.

join $ doSomething <$> getFirst <*> getSecond <*> getThird <*> getForth

This is a lovely time for Applicative Functors:

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

It works a bit like fmap in the previous answers I gave you today, but for larger numbers of arguments, like you have here.

Using functions like my hello with applicative functors helps you separate your IO code from the rest of the code, which is very good practice. Try to write hello instead of sayHello every time.

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

But for multiple inputs, we're out of luck. For whatever reason, the standard libs don't provide this:

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

You can, of course, just define it yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM