Haskell中的“辅助”功能

时间:2016-12-13 15:19:33

标签: function haskell

我的讲师目前有一种我以前从未见过的奇怪习惯,我想知道这是一个Haskell标准还是他编程风格的怪癖。

基本上,他经常做这样的事情:

functionEx :: String -> Int
functionEx s = functionExA s 0

functionExA :: String -> Int -> Int
functionExA s n = --function code

他称这些'辅助'函数,并且在大多数情况下,我可以看到的唯一优点是使用较少的提供参数来调用函数。但是大多数这些都隐藏在代码中,在我看来,在原始调用中添加参数更具可读性。

正如我所说,我并不是说我的观点是正确的,我之前没有看到过这样做,并且想知道它是否在Haskell中很常见。

2 个答案:

答案 0 :(得分:5)

是的,这很常见,而且不仅仅是在函数式编程中。在代码中将接口与代码分开是很好的做法(在这种情况下,这意味着函数签名:您必须传递的参数)来自实现的细节(需要在递归代码中使用计数器或类似代码)

在实际编程中,一种表现形式是具有默认参数或一个函数的多次重载。另一种常见的方法是返回或获取接口的实例,而不是实现该接口的特定类。在Java中,这可能意味着从方法而不是List返回ArrayList,即使您知道代码实际使用了ArrayList(其中ArrayList实现了List 1}}接口)。在Haskell中,类型类通常具有相同的功能。

“一开始应该为零的一个参数”模式偶尔发生在现实世界中,但它在函数式编程教学中尤为常见,因为你想要展示如何在递归样式中编写相同的函数。尾递归。包装函数对于证明两个实现实际上具有相同的结果也很重要。

在Haskell中,使用where更为常见,如下所示:

functionEx :: String -> Int
functionEx s = functionExA s 0 where
    functionExA s n = --function code

这样,即使存在“真实”功能也会从外部接口隐藏。没有理由公开这个函数(比如说)使用count参数进行尾递归这一事实。

答案 1 :(得分:2)

如果经常使用特殊情况定义,则执行此操作可能是有利的。例如,sum函数只是fold函数的一个特例。那么为什么我们不是每次只使用 if UIApplication.shared.canOpenURL(url){ print("Can open shared application url.") if #available(tvOS 10.0, *) { print("tvOS 10.0 detected") UIApplication.shared.open(url){res in //res is false... print("Result..." + String(res)) } } else { // Fallback on earlier versions UIApplication.shared.openURL(url) } } 而不是foldr (+) 0 [1, 2, 3]?因为sum [1,2,3]更具可读性。