如何在Haskell中使用curry函数

如何在Haskell中使用curry函数,haskell,currying,Haskell,Currying,我有一个函数multThree,用于将3个数字相乘,这与currying一起工作。然而,当我尝试用相同的结构将其扩展为四个数字相乘时,它不起作用。这是为什么?如何修复 multThree :: Num a => a -> (a -> (a -> a)) multThree x = (*) . (*) x multFour :: Num a => a -> (a -> (a -> (a -> a))) multFour x = (*) . (

我有一个函数multThree,用于将3个数字相乘,这与currying一起工作。然而,当我尝试用相同的结构将其扩展为四个数字相乘时,它不起作用。这是为什么?如何修复

multThree :: Num a => a -> (a -> (a -> a))
multThree x = (*) . (*) x

multFour :: Num a => a -> (a -> (a -> (a -> a)))
multFour x = (*) . (*) . (*) x
错误提示:

• Occurs check: cannot construct the infinite type: a ~ a -> a
  Expected type: a -> a -> a -> a
    Actual type: a -> (a -> a) -> a -> a
• In the expression: (*) . (*) . (*) x
  In an equation for ‘multFour’: multFour x = (*) . (*) . (*) x
• Relevant bindings include
    x :: a (bound at test2.hs:19:10)
    multFour :: a -> a -> a -> a -> a

让我们把它写出来,不用
()

所以我们看到,我们试图用一个数字乘以一个函数

关键错误是:

multFour x = (*) . multThree x
类型包括:

(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
因此,类型统一为:

a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
这不是你想要的类型

要修复代码,我建议:

multFour a b c d = a * b * c * d

这更具可读性。

让我们在不使用
(.)的情况下把它写出来。

所以我们看到,我们试图用一个数字乘以一个函数

关键错误是:

multFour x = (*) . multThree x
类型包括:

(*) :: Num a => a -> (a -> a)
multThree x :: Num b => b -> (b -> b)
x :: b
(.) :: (y -> z) -> (x -> y) -> (x -> z)
因此,类型统一为:

a = y
z = (a -> a)
b = x
y = b -> b
multFour :: Num b => b -> x -> z
multFour :: (Num b, Num (b -> b)) => b -> b -> (b -> b) -> (b -> b)
这不是你想要的类型

要修复代码,我建议:

multFour a b c d = a * b * c * d

这更容易阅读。

这不是关于咖喱(
multtree
已经咖喱了,因为它的类型是
a->a->a
,而不是
(a,a,a)->a
);这是关于组合高阶函数的。
multThree
的可怕的无点形式是
multThree=(*)。(*)
,这(老实说)几乎不值得理解,而只是编写非点自由版本。(
multFour=(((*)。(*))(*))(*)
甚至更糟。)如果您确实想要无点版本,可以使用
multThree=fmap(*)。(*)
multFour=fmap(fmap(*))。fmap(*)。(*)
=
fmap(fmap(*)。(*)。(*)
=
fmap多个。(*)
fmap
()
相同,但在我看来,这会使“跳过”参数的位置更加清晰。另一种构建无点解决方案的方法是,例如,
multThree=curry((*).uncurry(*)
:将元组中的两个参数配对,将它们相乘,然后将结果与另一个参数相乘。这与curry无关(
multThree
已经过时了,因为它的类型是
a->a->a
,而不是
(a,a)->a
);它是关于组合高阶函数的。
multThree
的可怕的无点形式是
multThree=(*)。(*)
,这(老实说)如果你真的想要一个无点版本,你可以使用
multThree=fmap(*)和
multFour=fmap(fmap(*)和
multFour=fmap(fmap(*)。fmap(*)如果你真的想要一个无点版本,你可以使用
multThree=fmap(*)和
multFour=fmap(fmap(*)fmap(*)。(*)
=
fmap(fmap(**)。(*))
=
fmap multThree.(*)
fmap
()
相同,但在我看来,在“跳过”参数的地方会更清楚一些。构建无点解决方案的另一种方法是,例如
multThree=curry((*).uncurry(*)
:将元组中的两个参数配对,将它们相乘,然后将结果与另一个参数相乘。