Haskell无点式编程 [英] Haskell pointfree programming
问题描述
1我试图了解Haskell中的pointfree编程,以及我对某些示例的疑问,因为我不太了解发生错误时给出的解释。 )我有一个循环函数定义如下:
myCycle :: [a] - > [a]
myCycle = foldr(++)[]。重复
为什么 myCycle = foldr(++)[] $ repeat
不工作?
2)用2添加列表的每个元素,然后添加另一个列表
sum :: [Int] - > [Int] - > [Int]
sum s = zipWith(+)。 map(+ 2)$ s
为什么函数与 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]
现在,您可以看到($)
根本不会改变类型。它的固定性确保你可以使用它而不是括号。让我们来看看它们的区别:
($)(foldr(++)[]):: [[a]] - > [a]
(。)(foldr(++)[])::(b - > [[a]]) - > b - >由于 repeat
的类型为
c - > [c]
,它不适用于($)
。它确实与(。)
有关,因为 c〜[a]
可以正常工作。
因此,请始终记住,($)
本身不会做任何事情。它仅仅改变了优先性/固定性。另外,如果您尝试理解/出现无点代码,则可以使用前缀符号而不是中缀:
sum l1 (+)(map(+2)l1)$ l2 = zipWith(+)(map(+2)l1) +2)l1))l2
- 摆脱($)和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 - 再次替换f和g
= zipWith(+)。(map(+2)$ l1
- 摆脱$和l1:
sum = zipWith(+)。map(+2)
I am trying to understand pointfree programming in Haskell and I questions on some examples, because I don't really understand the explanation given when the errors occur.
1) I have a cycle function defined below:
myCycle :: [a] -> [a]
myCycle = foldr (++) [] . repeat
Why does myCycle = foldr (++) [] $ repeat
not work?
2) Add every element of a list with 2 then add with another list
sum :: [Int] -> [Int] -> [Int]
sum s = zipWith (+) . map (+ 2) $ s
Why does the function has the same result with sum s = zipWith (+) $ map (+ 2) s
and why does sum l1 l2 = zipWith (+) . map (+ 2) $ l1 $ l2
not work
First of all, let's list all types:
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]
Now, as you can see, ($)
doesn't change the type at all. It's just so that its fixity makes sure that you can use it instead of parentheses. Let's see how they differ:
($) (foldr (++) []) :: [[a]] -> [a]
(.) (foldr (++) []) :: (b -> [[a]]) -> b -> [a]
Since repeat
has type c -> [c]
, it doesn't work with ($)
. It sure does with (.)
, since c ~ [a]
works fine.
So always keep in mind that ($)
doesn't do anything on its own. It merely changes the precedence/fixity. Also, it sometimes helps if you use prefix notation instead of infix if you try to understand/come to pointfree code:
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)
这篇关于Haskell无点式编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!