cbr*_*lak 82 syntax haskell function-composition
我试图理解点运算符在这个Haskell代码中做了什么:
sumEuler = sum . (map euler) . mkList
Run Code Online (Sandbox Code Playgroud)
整个源代码如下.
点运算符将两个函数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
Run Code Online (Sandbox Code Playgroud)
jro*_*way 131
简单来说,.就是函数组合,就像在数学中一样:
f (g x) = (f . g) x
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您正在创建一个新函数,sumEuler也可以像这样定义:
sumEuler x = sum (map euler (mkList x))
Run Code Online (Sandbox Code Playgroud)
示例中的样式称为"无点"样式 - 省略了函数的参数.在许多情况下,这使得代码更清晰.(第一次看到它时可能很难理解,但过了一会儿就会习惯它.这是一种常见的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
Jes*_*sak 24
的.运算符组成函数.例如,
a . b
Run Code Online (Sandbox Code Playgroud)
其中a和b是函数是一个新函数,它在其参数上运行b,然后在这些结果上运行.你的代码
sumEuler = sum . (map euler) . mkList
Run Code Online (Sandbox Code Playgroud)
与以下内容完全相同:
sumEuler myArgument = sum (map euler (mkList myArgument))
Run Code Online (Sandbox Code Playgroud)
但希望更容易阅读.地图euler周围有parens的原因是因为它更清楚地表明有3个函数被组成:sum,map euler和mkList - map euler是一个单独的函数.
Chr*_*way 22
sum是Haskell Prelude中的一个函数,而不是一个参数sumEuler.它有类型
Num a => [a] -> a
Run Code Online (Sandbox Code Playgroud)
函数组合运算符. 具有类型
(b -> c) -> (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)
所以我们有
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
Run Code Online (Sandbox Code Playgroud)
请注意,这Int是一个实例Num.
Haskell 中的点运算符
我试图了解点运算符在此 Haskell 代码中的作用:
Run Code Online (Sandbox Code Playgroud)sumEuler = sum . (map euler) . mkList
没有点的等效代码,那只是
sumEuler = \x -> sum ((map euler) (mkList x))
Run Code Online (Sandbox Code Playgroud)
或者没有 lambda
sumEuler x = sum ((map euler) (mkList x))
Run Code Online (Sandbox Code Playgroud)
因为点 (.) 表示函数组合。
首先,让我们简化eulerto的部分应用map:
map_euler = map euler
sumEuler = sum . map_euler . mkList
Run Code Online (Sandbox Code Playgroud)
现在我们只有点。这些点表示什么?
从来源:
Run Code Online (Sandbox Code Playgroud)(.) :: (b -> c) -> (a -> b) -> a -> c (.) f g = \x -> f (g x)
因此(.)是compose 运算符。
在数学中,我们可以将函数 f(x) 和 g(x) 的组合,即 f(g(x)) 写为
(f?g)(x)
可以读作“f由g组成”。
所以在 Haskell 中, f ? g,或由 g 组成的 f,可以写成:
f . g
Run Code Online (Sandbox Code Playgroud)
组合是结合的,这意味着用组合运算符编写的 f(g(h(x))) 可以毫无歧义地省略括号。
也就是说,由于 (f ? g) ? h 等价于 f ? (g ? h),我们可以简单地写成 f ? G ?H。
回到我们之前的简化,这个:
sumEuler = sum . map_euler . mkList
Run Code Online (Sandbox Code Playgroud)
只是意味着这sumEuler是这些功能的未应用组合:
sumEuler = \x -> sum (map_euler (mkList x))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45945 次 |
| 最近记录: |