let表达式中的模式匹配

时间:2010-06-20 06:09:48

标签: haskell syntax

如何从未知构造函数的变量中提取值?

例如,我想否定Either中的值,如果构造为右:

let Right x = getValue
in Right (negate x)

此代码成功将Right的值(在本例中为Int)绑定到x。

这样可行,但是如果getValue返回一个Left呢?有没有办法确定let表达式中变量的类型?或者有更好的方法来解决这个问题吗?

2 个答案:

答案 0 :(得分:18)

一般来说,你能做的是:

case getValue of
  Right x -> Right $ negate x
  e       -> e

这应该是清楚的:它就像函数参数中的模式匹配,而不是值。为了做你需要的,你有一个默认情况下捕获任何不匹配的东西,然后返回它。

但是,在您的特定情况下,您可以做一些更好的事情:

negate `fmap` getValue

或者,使用import Control.Applicative,您可以使用<$>作为fmapnegate <$> getValue)的同义词。 fmap函数的类型为fmap :: Functor f => (a -> b) -> f a -> f b。对于任何仿函数 1 fmap将普通值上的函数转换为仿函数中的函数。例如,列表是一个仿函数,对于列表,fmap = map。在此处,Either e代表一个仿函数,它是例外Left e或值Right a;将函数应用于Left不会执行任何操作,但将函数应用于Right会将其应用于Right。换句话说,

instance Functor (Either e) where
  fmap _ (Left l)  = Left l
  fmap f (Right r) = Right $ f r

因此,case版本是您问题的直接答案,但您的特定示例更接近于fmap

1:初看起来,仿函数是“容器”。如果您对各种类型的课程不满意,我建议您the Typeclassopedia进行全面参考;还有更多的教程,感受它们的最好方法就是与它们一起玩。但是,特定类型的fmap通常很容易使用(特别是在我看来,写<$>时)。

答案 1 :(得分:2)

回答这个问题的标题:
我认为“... where”和“let ... in ...”之间没有太大区别。两者都允许您声明几个函数参数绑定案例:

f val = let negR (Right x) = Right (negate x)
            negR y = y
        in negR val

let { negR (Right x) = Right (negate x); negR y = y; } in negR val