我试图理解点运算符在这个Haskell代码中做了什么:
sumEuler = sum . (map euler) . mkList
整个源代码如下.
点运算符将两个函数sum
以及结果map euler
和结果mkList
作为输入.
但是,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
jrockway.. 131
简单来说,.
就是函数组合,就像在数学中一样:
f (g x) = (f . g) x
在您的情况下,您正在创建一个新函数,sumEuler
也可以像这样定义:
sumEuler x = sum (map euler (mkList x))
示例中的样式称为"无点"样式 - 省略了函数的参数.在许多情况下,这使得代码更清晰.(第一次看到它时可能很难理解,但过了一会儿就会习惯它.这是一种常见的Haskell习语.)
如果您仍然感到困惑,可能有助于与 .
UNIX管道相关联.如果f
输出变为g
输入,其输出变为h
输入,则在命令行中将其写为f < x | g | h
.在Haskell中,.
像UNIX一样工作|
,但是"向后" - h . g . f $ x
.我发现这种符号在处理列表时非常有用.map (\x -> x * 2 + 10) [1..10]
你可以写一下,而不是像一些笨重的结构(+10) . (*2) <$> [1..10]
.(并且,如果您只想将该函数应用于单个值;它是(+10) . (*2) $ 10
.一致!)
Haskell wiki有一篇很好的文章,有更多细节:http://www.haskell.org/haskellwiki/Pointfree
简单来说,.
就是函数组合,就像在数学中一样:
f (g x) = (f . g) x
在您的情况下,您正在创建一个新函数,sumEuler
也可以像这样定义:
sumEuler x = sum (map euler (mkList x))
示例中的样式称为"无点"样式 - 省略了函数的参数.在许多情况下,这使得代码更清晰.(第一次看到它时可能很难理解,但过了一会儿就会习惯它.这是一种常见的Haskell习语.)
如果您仍然感到困惑,可能有助于与 .
UNIX管道相关联.如果f
输出变为g
输入,其输出变为h
输入,则在命令行中将其写为f < x | g | h
.在Haskell中,.
像UNIX一样工作|
,但是"向后" - h . g . f $ x
.我发现这种符号在处理列表时非常有用.map (\x -> x * 2 + 10) [1..10]
你可以写一下,而不是像一些笨重的结构(+10) . (*2) <$> [1..10]
.(并且,如果您只想将该函数应用于单个值;它是(+10) . (*2) $ 10
.一致!)
Haskell wiki有一篇很好的文章,有更多细节:http://www.haskell.org/haskellwiki/Pointfree
的.运算符组成函数.例如,
a . b
其中a和b是函数是一个新函数,它在其参数上运行b,然后在这些结果上运行.你的代码
sumEuler = sum . (map euler) . mkList
与以下内容完全相同:
sumEuler myArgument = sum (map euler (mkList myArgument))
但希望更容易阅读.地图euler周围有parens的原因是因为它更清楚地表明有3个函数被组成:sum,map euler和mkList - map euler是一个单独的函数.
sum
是Haskell Prelude中的一个函数,而不是一个参数sumEuler
.它有类型
Num a => [a] -> a
函数组合运算符.
具有类型
(b -> c) -> (a -> b) -> a -> c
所以我们有
euler :: Int -> Int map :: (a -> b ) -> [a ] -> [b ] (map euler) :: [Int] -> [Int] mkList :: Int -> [Int] (map euler) . mkList :: Int -> [Int] sum :: Num a => [a ] -> a sum . (map euler) . mkList :: Int -> Int
请注意,这Int
是一个实例Num
.
的.运算符用于函数组合.就像数学一样,如果你需要函数f(x)和g(x)f.g变为f(g(x)).
map是一个内置函数,它将函数应用于列表.通过将函数放在括号中,函数被视为参数.对此的一个术语是currying.你应该看一下.
它的作用是使用两个参数的函数,它应用参数euler.(地图欧拉)对吗?结果是一个新函数,它只需要一个参数.
总和.(地图euler).mkList基本上是将所有这些放在一起的奇特方式.我必须说,我的Haskell有点生疏,但也许你可以将最后一个功能放在一起吗?