简体   繁体   English

Haskell简化技术和monad

[英]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: 这是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. 它在今天我给你的答案中有点像fmap ,但对于大量的论点,就像你在这里一样。

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. 使用像我的hello和applicative functor这样的函数可以帮助你将IO代码与其余代码分开,这是非常好的做法。 Try to write hello instead of sayHello every time. 每次尝试用hello而不是sayHello来写。

Annoyingly, hoogle doesn't have an easy answer for this one. 令人讨厌的是,hoogle没有一个简单的答案。 This would be called bind2 . 这将被称为bind2 If it's a function with only one input, then you can use =<< , the infix version of what I'd call bind1 . 如果它只是一个输入的函数,那么你可以使用=<< ,即我称之为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. 当然,您可以自己定义它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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