function - Haskell 函数定义约定

标签 function haskell

我是 Haskell 的初学者。

根据我的学校资料,函数定义中使用的约定实际上如下

function_name arguments_separated_by_spaces = code_to_do

前任 :

f a b c = a * b +c

作为一名数学学生,我习惯于使用如下函数

function_name(arguments_separated_by_commas) =​​ code_to_do

前任 :
f(a,b,c) = a * b + c

它在 Haskell 中工作。

我的疑问是它是否适用于所有情况?

我的意思是我也可以在 Haskell 函数定义中使用传统的数学约定吗?

如果错了,在哪些特定情况下约定会出错?

提前致谢 :)

最佳答案

假设您要定义一个计算直角三角形斜边平方的函数。以下任一定义均有效

hyp1 a b = a * a + b * b

hyp2(a,b) = a * a + b * b

但是,它们的功能不一样!您可以通过查看它们在 GHCI 中的类型来判断
>> :type hyp1
hyp1 :: Num a => a -> a -> a

>> :type hyp2
hyp2 :: Num a => (a, a) -> a

hyp2首先(暂时忽略 Num a => 部分)类型告诉您该函数需要一对 (a, a)并返回另一个 a (例如,它可能需要一对整数并返回另一个整数,或者一对实数并返回另一个实数)。你像这样使用它
>> hyp2 (3,4)
25

请注意,括号在这里不是可选的!他们确保参数是正确的类型,一对 a s。如果你不包括它们,你会得到一个错误(现在你可能会觉得很困惑,但请放心,当你了解类型类时它会很有意义)。

现在看hyp1一种读取类型a -> a -> a的方法是否需要两个 a 类型的东西并返回 a 类型的其他内容.你像这样使用它
>> hyp1 3 4
25

现在,如果您确实包含括号,您将收到错误消息!

所以首先要注意的是,你使用函数的方式必须与你定义它的方式相匹配。如果用括号定义函数,则每次调用时都必须使用括号。如果在定义函数时不使用括号,那么在调用它时就不能使用它们。

因此,似乎没有理由偏爱其中一种——这只是口味问题。但实际上我认为有充分的理由更喜欢一个而不是另一个,你应该更喜欢不带括号的样式。有三个很好的理由:
  • 如果您没有使页面困惑的括号,它看起来更干净并且使您的代码更易于阅读。
  • 如果您在任何地方都使用括号,您将受到性能影响,因为您每次使用该函数时都需要构造和解构一对(尽管编译器可能会优化它 - 我不确定)。
  • 您想获得柯里化(Currying)的好处,也就是部分应用函数*。

  • 最后一点有点微妙。回想一下,我说过一种理解 a -> a -> a 类型函数的方法。是它需要两个 a 类型的东西, 并返回另一个 a .但是还有另一种读取该类型的方法,即 a -> (a -> a) .这意味着完全相同的事情,因为 ->运算符在 Haskell 中是右结合的。解释是该函数采用单个 a , 并返回 a -> a 类型的函数.这允许您只向函数提供第一个参数,然后再应用第二个参数,例如
    >> let f = hyp1 3
    >> f 4
    25
    

    这在各种情况下都非常有用。例如,map函数允许您将某些函数应用于列表的每个元素 -
    >> :type map
    map :: (a -> b) -> [a] -> [b]
    

    假设你有函数 (++ "!")这为任何 String 添加了一个爆炸.但是你有 Strings 的列表你希望他们都以一声巨响结束。没问题!您只需部分应用 map功能
    >> let bang = map (++ "!")
    

    现在bang是类型的函数**
    >> :type bang
    bang :: [String] -> [String]
    

    你可以像这样使用它
    >> bang ["Ready", "Set", "Go"]
    ["Ready!", "Set!", "Go!"]
    

    很实用!

    我希望我已经说服您,您学校的教育 Material 中使用的约定有一些非常充分的理由被使用。作为我自己具有数学背景的人,我可以看到使用更“传统”语法的吸引力,但我希望随着您在编程之旅中的进步,您将能够看到改变为最初有点的东西的优势你不熟悉。

    * 学究的注意事项 - 我知道柯里化(Currying)和部分应用并不完全相同。

    ** 实际上 GHCI 会告诉你类型是 bang :: [[Char]] -> [[Char]]但自从 String[Char] 的同义词这些意思是一样的。

    关于function - Haskell 函数定义约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22754726/

    相关文章:

    JavaScript 为什么 getItem() 有两种返回类型?

    Javascript 函数将我的值转换为未定义的值。我和我的老师不明白为什么

    algorithm - 关于遗传算法

    function - SAS 中的星期几函数

    haskell - 在 Haskell 中使用 2 个以上的参数进行柯里化(Currying)

    haskell - GHCi 中的缩进错误,实现过滤器

    javascript - 淡出功能以及 slidetoggle 功能

    haskell - 为什么我不能用 Haskell 端口号中相同值的变量替换某个值?

    list - 如何使 "time machine"在 Haskell 中工作?

    haskell - 使用 Control.Lens 组合镜头,其中必须调用中间函数