我如何将两个参数的Haskell函数重写为无点风格 [英] How do I re-write a Haskell function of two argument to point-free style

查看:114
本文介绍了我如何将两个参数的Haskell函数重写为无点风格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Haskell中有以下函数:

  agreeLen ::(等式a)=> [a]  - > [a]  - > Int 
agreeLen xy = length $ takeWhile(\(a,b) - > a == b)(zip xy)

我试图学习如何编写'惯用'Haskell,它似乎更喜欢使用 $ 而不是括号,并且在可能的情况下更喜欢无点代码。我似乎无法明确地提及 x y 。有任何想法吗?



我想我可能会遇到同样的问题,因为它没有任何两个参数的函数。



顺便说一下只是为了写出好的代码;不是一些使用任何东西来实现它的免费的作业练习。

谢谢。




b谢谢你的答案。你已经说服了我,这个功能并没有从无点使用中受益。你也给了我一些练习转换表达的很好的例子。对我来说,这仍然很困难,而且它们对于Haskell来说似乎是必不可少的,因为指针是指向C的。

解决方案



不是尽可能,而是它提高了可读性其他显而易见的优点)。



要免费获得您的交易$ / $>

  agreeLen xy = length $ takeWhile(\(a,b) - > a == b)(zip xy)

第一步是将($)右移,并用(。)

  agreeLen xy =长度。 takeWhile(\(a,b) - > a == b)$ zip xy 

现在,你可以把它移到更远的地方:

  agreeLen xy = length。 takeWhile(uncurry(==))。 zip x $ y 

在那里你可以马上砍掉一个参数,

  agreeLen x =长度。 takeWhile(uncurry(==))。 zip x 

然后您可以将其重写为组合运算符的前缀应用程序,

  agreeLen x =(。)(length。takeWhile(uncurry(==)))(zip x)

你可以写出

f(gx)

as

  f。 g $ x 

一般来说,这里有

 f =(。)(length。takeWhile(uncurry(==)))

g = zip ,给出

  agreeLen x =((。)(length。takeWhile(uncurry(==))))。 zip $ x 

参数 x 很容易被删除。然后,您可以将(。)的前缀应用程序转换为一个小节并获得

  agreeLen =((length。takeWhile(uncurry(==)))。)。 zip 

但是,这比原来的可读性差,所以我不建议这样做,除了练习表达式转化为无点式风格。


I have the following function in Haskell

agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile (\(a,b) -> a == b)  (zip x y)

I'm trying to learn how to write 'idiomatic' Haskell, which seem to prefer using . and $ instead of parenthesis, and also to prefer pointfree code where possible. I just can't seem to get rid of mentioning x and y explicitly. Any ideas?

I think I'd have the same issue with pointfreeing any function of two arguments.

BTW, this is just in pursuit of writing good code; not some "use whatever it takes to make it pointfree" homework exercise.

Thanks.


(Added comment) Thanks for the answers. You've convinced me this function doesn't benefit from pointfree. And you've also given me some great examples for practicing transforming expressions. It's still difficult for me, and they seem to be as essential to Haskell as pointers are to C.

解决方案

and also to prefer pointfree code where possible.

Not "where possible", but "where it improves readability (or has other manifest advantages)".

To point-free your

agreeLen x y = length $ takeWhile (\(a,b) -> a == b)  (zip x y)

A first step would be to move the ($) right, and replace the one you have with a (.):

agreeLen x y = length . takeWhile (\(a,b) -> a == b) $ zip x y

Now, you can move it even further right:

agreeLen x y = length . takeWhile (uncurry (==)) . zip x $ y

and there you can immediately chop off one argument,

agreeLen x = length . takeWhile (uncurry (==)) . zip x

Then you can rewrite that as a prefix application of the composition operator,

agreeLen x = (.) (length . takeWhile (uncurry (==))) (zip x)

and you can write

f (g x)

as

f . g $ x

generally, here with

f = (.) (length . takeWhile (uncurry (==)))

and g = zip, giving

agreeLen x = ((.) (length . takeWhile (uncurry (==)))) . zip $ x

from which the argument x is easily removed. Then you can transform the prefix application of (.) into a section and get

agreeLen = ((length . takeWhile (uncurry (==))) .) . zip

But, that is less readable than the original, so I don't recommend doing that except for practicing the transformation of expressions into point-free style.

这篇关于我如何将两个参数的Haskell函数重写为无点风格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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