sumListV3
如何运作? myFoldr
需要3个args:function,base case num和list。然而它以某种方式知道列表(基于您的输入),即使它从未在内部代码中指定。
我认为sumListV2
是最简单的。 sumListV3
如何编译,更不用说正常运行了?
myFoldr :: (a -> b -> b) -> b -> [a] -> b
myFoldr _ baseCase [] = baseCase
myFoldr f b (x:xs) = f x (myFoldr f b xs)
sumListV2 :: [Int] -> Int
sumListV2 xs = myFoldr (+) 0 xs
sumListV3 :: [Int] -> Int
sumListV3 = myFoldr (+) 0
答案 0 :(得分:8)
Haskell中的函数是“咖喱”的。
这意味着当你有一个函数f :: a -> b -> c
时,它实际上是a -> (b -> c)
,而f a b
实际上是(f a) b
(因为关联性规则)。
因此,当您运行f a b
时,它首先执行f a
,它会返回类型为b -> c
的新函数。然后,您可以给它b
并获得c
类型的最终答案。
这使您可以部分应用功能:
ghci> let add :: Int -> Int -> Int ; add a b = a + b
ghci> add 2 3
5
ghci> (add 2) 3
5
ghci> let addToTwo = add 2
ghci> :t addToTwo
addToTwo :: Int -> Int
ghci> addToTwo 6
8
ghci> addToTwo 9
11
sumListV3
的例子正在部分应用myFoldr
。 (此处根据您的情况指定类型。)
myFoldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int
myFoldr :: (Int -> Int -> Int) -> (Int -> ([Int] -> Int))
myFoldr (+) :: Int -> ([Int] -> Int)
myFoldr (+) 0 :: [Int] -> Int
sumListV3 :: [Int] -> Int
由于sumListV3
被定义为myFoldr (+) 0
,因此您可以在sumListV3
替换为myFoldr (+) 0
的位置:
sumListV3 [1,2]
= (myFoldr (+) 0) [1,2]
= myFoldr (+) 0 [1,2]
答案 1 :(得分:1)
通常在Haskell中有多种定义函数的方法。在这种情况下,您可以在参数xs
sumListV2 :: [Int] -> Int
sumListV2 xs = myFoldr (+) 0 xs
在这种情况下,在概念上与“通常的”C风格语法非常相似,在本例中为Javascript。
var sumListV2 = function(xs) {
return myFoldr(plusFunc, 0, xs)
}
或者您可以根据其他功能的组合来定义功能,也称为无点样式。
sumListV3 :: [Int] -> Int
sumListV3 = myFoldr (+) 0
在这种情况下,需要注意的是r.h.s.不是myFoldr
的返回值,但是,因为myFoldr
已经部分应用了*它的三个参数中的两个,所以它是一个函数,它接受剩下的一个列表。所以sumListV3
被定义为:一个列表的函数。
使用bind
部分应用myFold可以使用Javascript中的等效内容。
var sumListV2 = myFold.bind(null, plusFunc, 0);
关于Haskell的一个非常好的事情是它内置于语言中,因此您不需要额外的功能来进行部分应用。关于Haskell的一个棘手的问题,特别是来自其他语言,是你不需要额外的功能来进行部分应用;-)。棘手,因为模式匹配和部分应用的语法非常相似,而在其他语言中它们则截然不同。
*它没有提供整个图片,因为它更准确地深入研究currying以及Haskell中的每个函数只接受一个参数这一事实,而一个取3的函数是返回函数的函数“链”。但我发现它是一个有用的类比,特别是在与其他语言的部分应用程序进行比较时。