如何从未知构造函数的变量中提取值?
例如,我想否定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
特定类型通常很容易使用(特别是在我看来,写作时<$>
).