繁体   English   中英

Haskell简化技术和monad

[英]Haskell simplification technique and monads

如何减少/简化此代码(或通常,具有多个输入的代码)?

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

在这种情况下已经非常短,但当它达到多个输入时,它看起来很乱。 有什么方法可以做以下事情:

sayHello askSex askName

如果你

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

你可以写

join $ sayHello <$> askSex <*> askName

对于您的示例,您只获取两个参数,这不是一个大赢家。 但是对于更多的参数,它可以使代码更清晰。

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

这是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

它在今天我给你的答案中有点像fmap ,但对于大量的论点,就像你在这里一样。

使用像我的hello和applicative functor这样的函数可以帮助你将IO代码与其余代码分开,这是非常好的做法。 每次尝试用hello而不是sayHello来写。

令人讨厌的是,hoogle没有一个简单的答案。 这将被称为bind2 如果它只是一个输入的函数,那么你可以使用=<< ,即我称之为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

当然,您可以自己定义它。

暂无
暂无

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

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