免费在Haskell [英] Point-free in Haskell

查看:131
本文介绍了免费在Haskell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码,我想要免费;



(\kt - > chr $ a + flip mod 26(ord k + ord t -2 * a))



我该怎么做?



除了想想这个amd想出来的东西之外,还有一些免费样式的一般规则?

解决方案

要转一个函数

  func xyz =(x,y和z中的某些表达式)

成无点形式,我一般都会按照最后一个参数 z 并将函数写入

  func xyz =(使用x和y构建的一些函数管道)z 

然后我可以取消 z 获取

  func xy =(使用x和y构建的一些函数管道)
/ pre>

然后重复y和x的过程应该以免费的形式结束 func 。在这个过程中要认识到的一个重要转变是:

  fz = foo $ bar z  - 或fz = foo(bar z) 
< => f z = foo。 bar $ z
< => f = foo。 bar

同样重要的是要记住,通过部分评估,您可以中断最后一个参数一个函数:

  foo $ bar xy == foo。 bar x $ y  -  foo应用于((x x))应用于y)

功能,考虑 k t 的流程:


  1. ord 应用于每个

  2. 添加结果

  3. 减去2 * a

  4. 取结果mod 26

  5. 添加

  6. code> chr

所以作为简化的第一个尝试,我们得到:

  func kt = chr。 (+ a)。 (`mod` 26)。减去(2 * a)$ ord k + ord t 

请注意,您可以避免 flip 通过使用 mod 上的一节,使用 - 的部分会弄乱Haskell,所以有一个减法函数(他们与写负数的语法冲突:( - 2)表示负2 ,并且不相同 subtract 2 )。



在此函数中, ord k + ord t 是使用 Data.Function.on 链接)。这个有用的组合器让我们用 k 的函数替换 ord k + ord t t

  func kt = chr。 (+ a)。 (`mod` 26)。减去(2 * a)$((+)`on` ord)kt 

非常接近于

  func kt =(function pipeline)kt 

因此

  func =(function pipeline)

不幸的是,当组合一系列一元函数的二进制函数时,Haskell有点混乱,但是一个技巧(我会看看我能否找到一个很好的参考),我们最终得到:

 导入数据

func =((chr。(+ a)。(`mod` 26)。subtract(2 * a)))。 ((+)`on` ord)

这几乎是一个很好的无点无功功能管道,除了那个丑陋的戏法。通过在评论。:运算符=noreferrer>在这个页面上,这个整理了一点:

  import Data.Function )

(。:) =(。)。(。)

func =(chr。(+ a)。(`mod` 26)。subtract(2 * a))。:((+)`on` ord)

可以添加一些帮助函数,以从凯撒密码算术中分离字母< - > Int转换。例如: letterToInt =减去a。 ord


I have this code that I want to make point-free;

(\k t -> chr $ a + flip mod 26 (ord k + ord t -2*a))

How do I do that?

Also are there some general rules for point free style other than "think about this amd come up with something"?

解决方案

To turn a function

func x y z = (some expression in x, y and z)

into point-free form, I generally try to follow what is done to the last parameter z and write the function as

func x y z = (some function pipeline built using x and y) z

Then I can cancel out the zs to get

func x y = (some function pipeline built using x and y)

Then repeating the process for y and x should end up with func in point-free form. An essential transformation to recognise in this process is:

    f z = foo $ bar z    -- or f z = foo (bar z)
<=> f z = foo . bar $ z
<=> f   = foo . bar

It's also important to remember that with partial evaluation, you can "break off" the last argument to a function:

foo $ bar x y == foo . bar x $ y    -- foo applied to ((bar x) applied to y)

For your particular function, consider the flow that k and t go through:

  1. Apply ord to each of them
  2. Add the results
  3. Subtract 2*a
  4. Take the result mod 26
  5. Add a
  6. Apply chr

So as a first attempt at simplifying, we get:

func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ord k + ord t

Note that you can avoid flip by using a section on mod, and sections using - get messy in Haskell so there's a subtract function (they clash with the syntax for writing negative numbers: (-2) means negative 2, and isn't the same as subtract 2).

In this function, ord k + ord t is an excellent candidate for using Data.Function.on (link). This useful combinator lets us replace ord k + ord t with a function applied to k and t:

func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ((+) `on` ord) k t

We're now very close to having

func k t = (function pipeline) k t

and hence

func = (function pipeline)

Unfortunately Haskell is a bit messy when it comes to composing a binary function with a sequence of unary functions, but there is a trick (I'll see if I can find a good reference for it), and we end up with:

import Data.Function (on)

func = ((chr . (+a) . (`mod` 26) . subtract (2*a)) .) . ((+) `on` ord)

which is almost a nice neat point-free function pipeline, except for that ugly composing trick. By defining the .: operator suggested in the comments on this page, this tidies up a little to:

import Data.Function (on)

(.:) = (.).(.)

func = (chr . (+a) . (`mod` 26) . subtract (2*a)) .: ((+) `on` ord)

To polish this some more, you could add some helper functions to separate the letter <-> Int conversion from the Caesar cipher arithmetic. For example: letterToInt = subtract a . ord

这篇关于免费在Haskell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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