let表达式中的模式匹配

tit*_*coy 11 syntax haskell

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

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

let Right x = getValue
in Right (negate x)
Run Code Online (Sandbox Code Playgroud)

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

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

Ant*_*sky 18

一般来说,你能做的是:

case getValue of
  Right x -> Right $ negate x
  e       -> e
Run Code Online (Sandbox Code Playgroud)

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

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

negate `fmap` getValue
Run Code Online (Sandbox Code Playgroud)

或者,import Control.Applicative您可以将<$>其用作fmap(negate <$> getValue)的同义词.该fmap函数有类型fmap :: Functor f => (a -> b) -> f a -> f b.对于任何仿函数1,fmap将普通值上的函数转换为仿函数中的函数.例如,列表是一个仿函数,对于列表,fmap = map.这里,Either e表示一个异常Left e或值的仿函数Right a; 将函数应用于a Left什么都不做,但应用函数将其Right应用于Right.换一种说法,

instance Functor (Either e) where
  fmap _ (Left l)  = Left l
  fmap f (Right r) = Right $ f r
Run Code Online (Sandbox Code Playgroud)

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

1: 对于第一个近似,仿函数是"容器".如果您对各种类型不熟悉,我推荐使用Typeclassopedia进行全面参考; 还有更多的教程,感受它们的最好方法就是与它们一起玩.但是,fmap特定类型通常很容易使用(特别是在我看来,写作时<$>).

  • 并且不要忘记``Data.Either`中的左(右.否定)getValue`; (4认同)