在表达式的情况下匹配已分配的变量

时间:2015-10-02 09:36:57

标签: haskell pattern-matching

如果Erlang中的以下代码等同于分配给Four的值,则该代码的值为3;

run() ->
    Four = 4,
    case 3 of
        Four -> io:format("3 == 4~n", []);
        _ -> io:format("3 /= 4~n", [])
    end.

执行时打印出“3 / = 4”。 Haskell中的类似代码:

main = do
    let four = 4
    case 3 of
        four -> putStrLn "3 == 4"
        _ -> putStrLn "3 /= 4"

打印“3 == 4”这是一个声明,我不是(在我生命中的这一点)准备接受为真理。

为什么Haskell不让我匹配以前绑定的变量?它是每个设计还是仅仅是一个do-notation的结果(顺便说一下表达式的情况,我测试了在一个案例中将名称绑定到一个值...然后在另一个案例中匹配它...它没有工作)实施? 有没有办法让它工作,像Erlang一样酷或简单,还是我必须手动比较它们?

2 个答案:

答案 0 :(得分:4)

这来自一般的静态范围规则,以及变量的重命名(alpha-conversion)。例如。我们知道

(\x -> x + 1)

相同
(\y -> y + 1)

在任何情况下。这对其他绑定器的工作方式相同:

let x = 1 in f x  -- is the same as
let y = 1 in f y

另外

case e of x -> f x -- is the same as
case e of y -> f y

某些语言,例如Erlang,决定打破这种常规重命名规则,特殊外壳模式匹配外部作用域中定义的变量。 我说大多数功能语言都决定遵循它。

在Haskell中,您可以使用

实现相同目的
case e of v | v == previousVariable -> ...

请注意,这需要(==),因此Eq实例必须可用。也就是说,它适用于Int s,但不适用于函数(或缺少比较器的其他类型)。

答案 1 :(得分:0)

在这种情况下,Haskell不会将four = 43的值four作为模式(在这种情况下会抓住所有内容)进行比较因此,-> four的右侧现在为four == 3(它会影响上面的绑定)

你可能想要

let four = 4
case 3 of
    x | four == x -> putStrLn "3 == 4"
      | otherwise -> putStrLn "3 /= 4"

inestead