了解Data.Function.on类型签名

时间:2017-07-23 03:42:57

标签: haskell type-signature

当谈到Haskell语法和函数式编程语言时,我仍然是初学者,所以当我查看Data.Function.on on :: (b -> b -> c) -> (a -> b) -> a -> a -> c的类型声明时,我的解释是需要四个参数:(b -> b -> c)(a -> b)aa,并返回c。但是,当我查看Data.Function.on的通用语法(*) `on` f = \x y -> f x * f y时,它只接受两个函数参数,而不是四个,那么类型签名与使用语法有何关系?

3 个答案:

答案 0 :(得分:3)

  

我的解释是它需要四个参数

所有Haskell函数都有一个参数。其中一些只是返回其他功能。

查看on签名的最佳方式是作为高阶函数:(b -> b -> c) -> (a -> b) -> (a -> a -> c)。这说'#34;如果你给我一个二元运算符,它需要b s并给出c以及从b获得a s的方法,我会给你一个二元运算符,它接受a s并给出c"。您可以在定义中看到这一点:

(*) `on` f = \x y -> f x * f y

答案 1 :(得分:1)

函数类型的Haskell箭头隐藏了一个简单但聪明的想法。您必须将->视为运算符,例如+-,但对于类型。它有两种类型作为参数,并为您提供一个由函数组成的新类型。所以在

Int -> String

您有类型IntString,并且您可以获得从Int到String的函数。

就像任何其他运算符一样,您需要一个规则来链接它们。如果你想到-,这是什么意思?

10 - 6 - 4

(10 - 6) - 4 = 0还是10 - (6 - 4) = 8?答案是第一个,这就是为什么我们说-是"左关联"。

->运算符是右关联的,所以

foo :: Int -> String -> String

实际上意味着

foo :: Int -> (String -> String)

想想这意味着什么。这意味着foo不会接受2个参数并返回类型String的结果,它实际上需要1个参数(Int)并返回一个新的函数,它接受第二个参数(String)并返回最终String

函数应用程序的工作方式相同,只是左关联。所以

foo 15" wibble"

实际上意味着

(foo 15)" wibble"

因此foo已应用于15并返回一个新函数,然后将其应用于"wibble"

这导致了一个巧妙的技巧:在调用函数时不必提供所有参数(就像在其他几乎所有编程语言中一样),你可以只提供第一个或前几个,并得到返回一个需要其余参数的新函数。

这是on发生的事情。我将使用更具体的版本,其中包括' f'被' length'取代。

(*)on长度

你给on前两个参数。结果是一个新功能,期望其他两个。在类型中,

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c

在这种情况下,(*)的类型为Num n => n -> n -> n(我使用不同的字母来减少混淆),因此与{{1}的第一个参数的类型相匹配},得出的结论是,如果on替换了类型b,那么类型n必须也是,并且也必须是c个实例。因此Num必须返回一些数字类型。碰巧的是,length的类型为length,而[d] -> IntInt的实例,因此可以解决问题。所以在最后你会得到:

Num

答案 2 :(得分:0)

作为一种直观的帮助,我将其理解为“如果您给我一个b类型的比较器,并且是一种从的值中提取b类型的值的方法类型a,我会给你一个类型为a比较器

例如如果a是某种复合数据类型,而b是这些数据值的某些数字属性,则可以表达使用Data.Function.on对这些复合数据类型进行排序的想法。