用2个以上的参数在Haskell中进行咖喱

mol*_*ac8 3 haskell currying pointfree tacit-programming

我开始学习Haskell,所以我也需要了解curring(这也是我第一次看到这种技术)。我想我知道在某些情况下,数字化仅“消除”参数之一是如何工作的。就像在下一个示例中,我试图计算4个数字的乘积。这是未固化的函数:

prod :: Integer->Integer->Integer->Integer->Integer
prod x y z t = x * y * z * t
Run Code Online (Sandbox Code Playgroud)

这是咖喱函数:

prod' :: Integer->Integer->Integer->Integer->Integer
prod' x y z = (*) (x*y*z)
Run Code Online (Sandbox Code Playgroud)

但是我不明白如何继续这种动态变化,例如仅使用两个参数来执行相同的功能,依此类推:

prod'' :: Integer->Integer->Integer->Integer->Integer
prod'' x y =
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

这是未固化的函数:

prod :: Integer -> Integer -> Integer -> Integer -> Integer
prod x y z t = x * y * z * t
Run Code Online (Sandbox Code Playgroud)

已经是咖喱函数。实际上,Haskell中的所有功能都是自动管理的。确实,您在这里编写了一个类似于以下内容的函数:

prod :: Integer -> (Integer -> (Integer -> (Integer -> Integer)))
Run Code Online (Sandbox Code Playgroud)

Haskell将因此产生一个类似于以下内容的函数:

prod :: Integer -> (Integer -> (Integer -> (Integer -> Integer)))
prod = \x -> (\y -> (\z -> (\t -> x * y * z * t)))
Run Code Online (Sandbox Code Playgroud)

实际上,我们可以例如生成以下功能:

prod2 = prod 2
Run Code Online (Sandbox Code Playgroud)

它将具有以下类型:

prod2 :: Integer -> (Integer -> (Integer -> Integer))
prod2 = prod 2
Run Code Online (Sandbox Code Playgroud)

我们可以继续:

prod2_4 :: Integer -> (Integer -> Integer)
prod2_4 = prod2 4
Run Code Online (Sandbox Code Playgroud)

最终:

prod2_4_6 :: Integer -> Integer
prod2_4_6 = prod2_4 6
Run Code Online (Sandbox Code Playgroud)

编辑

该函数prod'具有:

prod'' x y = (*) ((*) (x*y))
Run Code Online (Sandbox Code Playgroud)

因为那意味着您要乘(*) (x*y)以下一个参数。而是(*) (x*y)一个功能。您只能将数字相乘。严格来说,您可以使函数编号。但是Haskell编译器因此抱怨:

Prelude> prod'' x y = (*) ((*) (x*y))

<interactive>:1:1: error:
    • Non type-variable argument in the constraint: Num (a -> a)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        prod'' :: forall a.
                  (Num (a -> a), Num a) =>
                  a -> a -> (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)

因此,这表示您的目标是使用一个函数a -> a作为第一个操作数来执行操作,但是该函数不是Num类型类的实例。