我试图理解Haskell中的无点编程,并且我对一些例子提出了疑问,因为我并不真正理解错误发生时给出的解释.
1)我有一个循环函数定义如下:
myCycle :: [a] -> [a]
myCycle = foldr (++) [] . repeat
Run Code Online (Sandbox Code Playgroud)
为什么不起作用myCycle = foldr (++) [] $ repeat?
2)用2添加列表的每个元素,然后添加另一个列表
sum :: [Int] -> [Int] -> [Int]
sum s = zipWith (+) . map (+ 2) $ s
Run Code Online (Sandbox Code Playgroud)
为什么函数有同样的结果sum s = zipWith (+) $ map (+ 2) s?为什么sum l1 l2 = zipWith (+) . map (+ 2) $ l1 $ l2不工作
首先,让我们列出所有类型:
foldr :: (a -> b -> b) -> b -> [a] -> b
(++) :: [a] -> [a] -> [a]
[] :: [a]
repeat :: a -> [a]
(.) :: (b -> c) -> (a -> b) -> a -> c
($) :: (a -> b) -> a -> b
foldr (++) :: [a] -> [[a]] -> [a]
foldr (++) [] :: [[a]] -> [a]
Run Code Online (Sandbox Code Playgroud)
现在,正如您所看到的,($)根本不会改变类型.它的固定性确保您可以使用它而不是括号.让我们看看他们有何不同:
($) (foldr (++) []) :: [[a]] -> [a]
(.) (foldr (++) []) :: (b -> [[a]]) -> b -> [a]
Run Code Online (Sandbox Code Playgroud)
由于repeat有类型c -> [c],它不起作用($).确实如此(.),因为c ~ [a]工作正常.
因此,请始终牢记,($)它本身不会做任何事情.它只是改变了优先级/固定性.此外,如果您尝试理解/来到无点代码,如果您使用前缀表示法而不是中缀,它有时会有所帮助:
sum l1 l2 = zipWith (+) (map (+2) l1) l2
= zipWith (+) (map (+2) l1) $ l2
= ($) (zipWith (+) (map (+2) l1)) l2
-- get rid of both ($) and l2:
sum l1 = zipWith (+) (map (+2) l1)
= (zipWith (+)) ((map (+2)) l1)
= f (g l1) -- f = zipWith (+), g = map (+2)
= (f . g) l1
= (zipWith (+) . (map (+2)) l1 -- substitute f and g again
= zipWith (+) . (map (+2) $ l1
-- get rid of $ and l1:
sum = zipWith (+) . map (+2)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
150 次 |
| 最近记录: |