Igo*_*gor 17 haskell coding-style pointfree
我有这个代码,我想做点无关;
(\k t -> chr $ a + flip mod 26 (ord k + ord t -2*a))
我怎么做?
除了"想想这个和某些东西"之外,还有一些关于点自由风格的一般规则吗?
Nef*_*byr 52
转一个功能
func x y z = (some expression in x, y and z)
Run Code Online (Sandbox Code Playgroud)
对于无点形式,我通常会尝试按照对最后一个参数所做的操作z并将函数写为
func x y z = (some function pipeline built using x and y) z
Run Code Online (Sandbox Code Playgroud)
然后我可以取消zs得到
func x y = (some function pipeline built using x and y)
Run Code Online (Sandbox Code Playgroud)
然后重复y和x的过程应该func以无点形式结束.在这个过程中认识到的一个重要转变是:
f z = foo $ bar z -- or f z = foo (bar z)
<=> f z = foo . bar $ z
<=> f = foo . bar
Run Code Online (Sandbox Code Playgroud)
同样重要的是要记住,通过部分评估,您可以"中断"函数的最后一个参数:
foo $ bar x y == foo . bar x $ y -- foo applied to ((bar x) applied to y)
Run Code Online (Sandbox Code Playgroud)
为了您的特定功能,考虑到流动是k和t经历:
ord于他们每个人chr因此,作为简化的第一次尝试,我们得到:
func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ord k + ord t
Run Code Online (Sandbox Code Playgroud)
请注意,你可以避免flip使用一节mod,并-在Haskell中使用get messy 的部分,所以有一个subtract函数(它们与编写负数的语法冲突:(-2)表示负2,并且不相同subtract 2).
在这个函数中,ord k + ord t是使用Data.Function.on(链接)的一个很好的候选者.这个有用的组合器让我们可以替换ord k + ord t为应用于的函数k和t:
func k t = chr . (+a) . (`mod` 26) . subtract (2*a) $ ((+) `on` ord) k t
Run Code Online (Sandbox Code Playgroud)
我们现在非常接近
func k t = (function pipeline) k t
Run Code Online (Sandbox Code Playgroud)
因此
func = (function pipeline)
Run Code Online (Sandbox Code Playgroud)
不幸的是,Haskell在用一系列一元函数组成二进制函数时有点乱,但有一个技巧(我会看看我是否可以找到一个很好的参考),我们最终得到:
import Data.Function (on)
func = ((chr . (+a) . (`mod` 26) . subtract (2*a)) .) . ((+) `on` ord)
Run Code Online (Sandbox Code Playgroud)
除了那个丑陋的构图技巧之外,这几乎是一个很好的简洁无点功能管道.通过定义本页.:评论中建议的运算符,这可以整理一下:
import Data.Function (on)
(.:) = (.).(.)
func = (chr . (+a) . (`mod` 26) . subtract (2*a)) .: ((+) `on` ord)
Run Code Online (Sandbox Code Playgroud)
为了更好地完善这一点,您可以添加一些辅助函数来将字母< - > Int转换与Caesar密码算术分开.例如:letterToInt = subtract a . ord
| 归档时间: |
|
| 查看次数: |
4151 次 |
| 最近记录: |