你如何使用Control.Applicative编写清洁器Haskell? [英] How do you use Control.Applicative to write cleaner Haskell?

查看:155
本文介绍了你如何使用Control.Applicative编写清洁器Haskell?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在最近回答风格问题,我写了

  main = untilM(isCorrect 42)(读`liftM` getLine)

  isCorrect num guess = 
case比较num猜测
EQ - > putStrLn你赢了! >>返回True
...

Martijn 有帮助的建议替代品:

  main = untilM(isCorrect 42) < $> getLine)

EQ - >真的< $ putStrLn你赢了!

通过使用 Control.Applicative ?什么是有用的经验法则记住有效地使用Control.Applicative?

解决方案

在回答中有很多要说的如果你使用的是 do $ c> -notation并且您生成的值[1]不用于您正在排序的表达式[2],那么该代码可以转换为Applicative风格。同样,如果在排序的表达式中使用一个或多个生成的值,则必须使用 Monad Applicative

 做一个<  -  e1 
b< - e2
c< - e3
return(fabc)

我们发现在< - 右边没有任何一个表达式任何生成的值( a b c )出现。因此,我们可以将其转换为使用Applicative代码。这是一个可能的转变:

  f <$> e1 * e2 * e3 

和另一个:

  liftA3 f e1 e2 e3 

另一方面,拿这块代码例如:

  do a<  -  e1 
b< - e2 a
c< - e3
return(fbc)

此代码不能使用 Applicative [3],因为生成的值 a 稍后会在理解的表达式中使用。这必须使用 Monad 来得到它的结果 - 尝试将它分解到 Applicative 中以了解原因。

这个主题还有一些有趣的和有用的细节,但是,我只是想给你一个经验法则,你可以浏览一个 do -comprehension,如果可以将它分解为 Applicative 样式代码,则可以很快确定。



[1]那些出现在< - 左边的。



[2]表达式出现在< - 右边。



严格地说,它的一部分可以通过分解out e2 a


In a recent answer to a style question, I wrote

main = untilM (isCorrect 42) (read `liftM` getLine)

and

isCorrect num guess =
  case compare num guess of
    EQ -> putStrLn "You Win!" >> return True
    ...

Martijn helpfully suggested alternatives:

main = untilM (isCorrect 42) (read <$> getLine)

EQ -> True <$ putStrLn "You Win!"

Which common patterns in Haskell code can be made clearer using abstractions from Control.Applicative? What are helpful rules of thumb to keep in mind for using Control.Applicative effectively?

解决方案

There is a lot to say in answer to your question, however, since you asked, I will offer this "rule of thumb."

If you are using do-notation and your generated values[1] are not used in the expressions that you are sequencing[2], then that code can transform to an Applicative style. Similarly, if you use one or more of the generated values in an expression that is sequenced, then you must use Monad and Applicative is not strong enough to achieve the same code.

For example, let us look at the following code:

do a <- e1
   b <- e2
   c <- e3
   return (f a b c)

We see that in none of the expressions to the right of <- do any of the generated values (a, b, c) appear. Therefore, we can transform it to using Applicative code. Here is one possible transformation:

f <$> e1 <*> e2 <*> e3

and another:

liftA3 f e1 e2 e3

On the other hand, take this piece of code for example:

do a <- e1
   b <- e2 a
   c <- e3
   return (f b c)

This code cannot use Applicative[3] because the generated value a is used later in an expression in the comprehension. This must use Monad to get to its result -- attempt to factor it into Applicative to get a feel for why.

There are some further interesting and useful details on this subject, however, I just intended to give you this rule of thumb whereby you can skim over a do-comprehension and determine pretty quickly if it can be factored into Applicative style code.

[1] Those that appear to the left of <-.

[2] Expressions that appear to the right of <-.

[3] strictly speaking, parts of it could, by factoring out e2 a.

这篇关于你如何使用Control.Applicative编写清洁器Haskell?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆