在Haskell中的点运算符:需要更多的解释

我试图了解点运算符在这个Haskell代码中做了什么:

sumEuler = sum . (map euler) . mkList 

整个源代码如下。

我的理解

点运算符将两个函数summap euler mkList的结果以及mkList的结果作为input。

但是, sum不是函数,它是函数的参数,对吗? 那么这里发生了什么?

另外, (map euler)在做什么?

 mkList :: Int -> [Int] mkList n = [1..n-1] euler :: Int -> Int euler n = length (filter (relprime n) (mkList n)) sumEuler :: Int -> Int sumEuler = sum . (map euler) . mkList 

简单地说, . 是function组成,就像math一样:

 f (gx) = (f . g) x 

在你的情况下,你正在创build一个新的函数, sumEuler也可以像这样定义:

 sumEuler x = sum (map euler (mkList x)) 

您示例中的样式被称为“无点”样式 – 省略了该函数的参数。 这在很多情况下使代码更清晰。 (第一次看到它可能很难,但过一会儿你就会习惯了,这是一个常见的Haskell习惯用法。)

如果你仍然困惑,这可能有助于联系. 像一个UNIXpipe道。 如果f的输出变成g的input,其输出变成h的input,你可以在命令行上写出如f < x | g | h f < x | g | h f < x | g | h 。 在Haskell中. 像UNIX | ,但是“倒退” – h . g . f $ x h . g . f $ x h . g . f $ x 。 我发现这个表示法在处理列表的时候非常有用。 不要像map (\x -> x * 2 + 10) [1..10]这样笨拙的构造,你可以写(+10) . (*2) <$> [1..10] (+10) . (*2) <$> [1..10] 。 (而且,如果您只想将该函数应用于单个值, (+10) . (*2) $ 10一致!)

Haskell wiki有一个很好的文章,更详细一些: http : //www.haskell.org/haskellwiki/Pointfree

sum是Haskell Prelude中的函数,不是sumEuler的参数。 它有types

 Num a => [a] -> a 

函数组合运算符. 有types

 (b -> c) -> (a -> b) -> a -> c 

所以我们有

 sum :: Num a => [a] -> a map :: (a -> b) -> [a] -> [b] euler :: Int -> Int mkList :: Int -> [Int] (map euler) :: [Int] -> [Int] (map euler) . mkList :: Int -> [Int] sum . (map euler) . mkList :: Int -> Int 

请注意, IntNum一个实例。

的。 操作员组成function。 例如,

 a . b 

其中ab是函数是一个新的函数 ,运行b的参数,然后一个对这些结果。 你的代码

 sumEuler = sum . (map euler) . mkList 

与以下内容完全相同:

 sumEuler myArgument = sum (map euler (mkList myArgument)) 

但希望更容易阅读。 地图欧拉附近有人的原因是因为它更清晰地表示了3个function: summap eulermkListmap euler是一个单一的function。

编辑:删除有关优先顺序的错误信息。

的。 运算符用于函数组合。 就像math一样,如果你必须函数f(x)和g(x)f。 g变成f(g(x))。

map是一个内置函数,它将一个函数应用于一个列表。 通过将函数放在括号中,该函数被视为一个参数。 这个术语是咖啡 。 你应该看看。

什么是做它是采用一个函数与所说的两个参数,它应用参数欧拉。 (地图欧拉)对不对? 结果是一个新的函数,只有一个参数。

总和。 (地图欧拉)。 mkList基本上是把所有这些放在一起的奇特方式。 我必须说,我的Haskell有点生疏,但也许你可以把最后一个function放在一起吗?

点运算符将左侧的函数( sum )应用于右侧函数的输出。 在你的情况下,你一起链接几个函数 – 你将mkList的结果mkList(map euler) mkList (map euler) ,然后把结果传递给sum 。 这个网站很好的介绍了几个概念。