首页 > 解决方案 > 在 Haskell 中使用 2 个以上的参数进行柯里化

问题描述

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

prod :: Integer->Integer->Integer->Integer->Integer
prod x y z t = x * y * z * t

这是咖喱函数:

prod' :: Integer->Integer->Integer->Integer->Integer
prod' x y z = (*) (x*y*z)

但我不明白我怎么能继续这种动态,例如只用两个参数做同样的函数等等:

prod'' :: Integer->Integer->Integer->Integer->Integer
prod'' x y =

标签: haskellcurryingpointfreetacit-programming

解决方案


这是未经处理的函数:

prod :: Integer -> Integer -> Integer -> Integer -> Integer
prod x y z t = x * y * z * t

已经是一个柯里化函数。事实上,Haskell 中的所有函数都是自动柯里化的。实际上,您在这里编写了一个如下所示的函数:

prod :: Integer -> (Integer -> (Integer -> (Integer -> Integer)))

Haskell 将因此生成一个如下所示的函数:

prod :: Integer -> (Integer -> (Integer -> (Integer -> Integer)))
prod = \x -> (\y -> (\z -> (\t -> x * y * z * t)))

事实上,我们可以例如生成这样的函数:

prod2 = prod 2

这将具有类型:

prod2 :: Integer -> (Integer -> (Integer -> Integer))
prod2 = prod 2

我们可以继续:

prod2_4 :: Integer -> (Integer -> Integer)
prod2_4 = prod2 4

最终:

prod2_4_6 :: Integer -> Integer
prod2_4_6 = prod2_4 6

编辑

具有以下功能的功能prod'

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

因为这意味着你乘(*) (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

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


推荐阅读