根据第一个参数在函数内创建一个新函数

时间:2018-04-15 13:32:46

标签: haskell

所以我有一个返回函数的函数。返回的函数应该为除x 之外的所有输入返回0。对于x,它应该返回10。

g x = do
        let 
            f x = 10
            f _ = 0  
        f

但是函数总是返回10:

(g 3) 4 
10

似乎参数x与用于创建函数f的x不同。那我怎么能实现呢?

3 个答案:

答案 0 :(得分:3)

您的方法似乎是尝试使用pattern matching类似unification - Haskell不执行统一,模式匹配仅适用于数据构造函数(例如Just) ,而不是价值观。

您在内部定义shadows中使用的名称x外部定义中使用的名称x - 因此您的内部函数等同于:

f x = 10

您应该使用不同的变量名,并使您的内部函数将其参数与外部函数的参数进行比较:

g x = let f y = if x == y then 10 else 0
      in f

或使用currying,这可以说是更好的风格:

g x y = if x == y then 10 else 0

这在语义上等同于上面的版本,并且在语义上等同于返回lambda的函数。我们可以将g部分应用于一个值来生成一个带有一个参数的函数,例如:

> (g 3) 4
0
> (g "hi") "hi"
10

答案 1 :(得分:1)

模式匹配“f X ”仅当 X 是文字或数据构造函数(如“True”)时才将参数与 X 进行比较。当 X 是一个变量时,它会绑定一个新变量 - 在这种情况下,另一个“x”会遮挡外部变量。你必须使用良好的旧比较。例如,有警卫:

f y | x == y = ...
f _ = ...

答案 2 :(得分:1)

Haskell不允许统一具有相同名称的变量。

例如,f x x = ...是语法错误,而不是说“当第一个和第二个参数相等时匹配这种情况”。

在您的情况下,您有相同的概念问题,但没有语法错误,因为一旦您尝试使用x中的参数匹配它,Haskell只会从g隐藏f。由于在没有构造函数的情况下匹配变量x是无条件的,因此它总是成功并返回10.

你想要一个像这样的函数:

g x = \y -> if x == y then 10 else 0

明确使用(==)运算符。