如果模式与“可能是”结果匹配
If pattern matching with `Maybe a` result
以下代码说明了我的意图。我想模式匹配,如果不匹配结果是Nothing
,如果匹配结果是Just something
data MyData =
A Int
| B String
| C
ifA (A i) = Just i
ifA _ = Nothing
ifB (B str) = Just str
ifB _ = Nothing
ifC C = Just ()
ifC _ = Nothing
mbMult3 i = Just (i*3)
concWorld str = Just (str ++ "World")
example1 v = ifA v >>= mbMult3
example2 v = ifB v >>= concWorld
-- example2 (B "Hello ,") == Just "Hello, World"
-- example2 (A 3) == Nothing
还有其他方法吗ifA
ifB
ifC
。
编辑:
- 我怀疑
lens
图书馆可能有一些东西。但是我现在对lens
一无所知。
- 已更新
ifC
Prisms† from the lens package model this. You can generate prisms for your type using makePrisms
, then use ^?
(or its prefix equivalent, preview
) 访问 sum 类型的成员,如果提供了不同的值,则生成 Nothing
:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data MyData
= A Int
| B String
| C
deriving (Show)
makePrisms ''MyData
ghci> A 42 ^? _A
Just 42
ghci> A 42 ^? _B
Nothing
ghci> C ^? _C
Just ()
棱镜的好处在于它们可以与其他光学器件组合(例如 lenses, folds, and traversals),以及使用它们通过组合棱镜来遍历嵌套的求和类型:
ghci> (A 42, C) ^? _1._A
Just 42
ghci> (B "hello", C) ^? _1._A
Nothing
ghci> Just (A 42) ^? _Just._A
Just 42
ghci> Just (B "hello") ^? _Just._A
Nothing
ghci> Nothing ^? _Just._A
Nothing
lens 包相当复杂,解释它的所有功能完全超出了这个答案的范围。如果您不需要太多,您的解决方案可能没问题。但是,如果您发现自己经常编写此类代码,那么镜头可能会有所帮助,只要您愿意接受陡峭的学习曲线和经常令人困惑的类型错误。
† 更一般地说,^?
适用于任何产生零值或一个值(或更多,它只忽略除第一个值以外的所有值)的 Fold
,但棱镜是专为求和类型而设计,因此它们在这里更相关。
这是我不时使用的一个可爱的成语,因为我还没有戴上镜头。
{-# LANGUAGE MonadComprehensions #-}
example1 v = [ x | A x <- pure v ] >>= mbMult3
以下代码说明了我的意图。我想模式匹配,如果不匹配结果是Nothing
,如果匹配结果是Just something
data MyData =
A Int
| B String
| C
ifA (A i) = Just i
ifA _ = Nothing
ifB (B str) = Just str
ifB _ = Nothing
ifC C = Just ()
ifC _ = Nothing
mbMult3 i = Just (i*3)
concWorld str = Just (str ++ "World")
example1 v = ifA v >>= mbMult3
example2 v = ifB v >>= concWorld
-- example2 (B "Hello ,") == Just "Hello, World"
-- example2 (A 3) == Nothing
还有其他方法吗ifA
ifB
ifC
。
编辑:
- 我怀疑
lens
图书馆可能有一些东西。但是我现在对lens
一无所知。 - 已更新
ifC
Prisms† from the lens package model this. You can generate prisms for your type using makePrisms
, then use ^?
(or its prefix equivalent, preview
) 访问 sum 类型的成员,如果提供了不同的值,则生成 Nothing
:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data MyData
= A Int
| B String
| C
deriving (Show)
makePrisms ''MyData
ghci> A 42 ^? _A
Just 42
ghci> A 42 ^? _B
Nothing
ghci> C ^? _C
Just ()
棱镜的好处在于它们可以与其他光学器件组合(例如 lenses, folds, and traversals),以及使用它们通过组合棱镜来遍历嵌套的求和类型:
ghci> (A 42, C) ^? _1._A
Just 42
ghci> (B "hello", C) ^? _1._A
Nothing
ghci> Just (A 42) ^? _Just._A
Just 42
ghci> Just (B "hello") ^? _Just._A
Nothing
ghci> Nothing ^? _Just._A
Nothing
lens 包相当复杂,解释它的所有功能完全超出了这个答案的范围。如果您不需要太多,您的解决方案可能没问题。但是,如果您发现自己经常编写此类代码,那么镜头可能会有所帮助,只要您愿意接受陡峭的学习曲线和经常令人困惑的类型错误。
† 更一般地说,^?
适用于任何产生零值或一个值(或更多,它只忽略除第一个值以外的所有值)的 Fold
,但棱镜是专为求和类型而设计,因此它们在这里更相关。
这是我不时使用的一个可爱的成语,因为我还没有戴上镜头。
{-# LANGUAGE MonadComprehensions #-}
example1 v = [ x | A x <- pure v ] >>= mbMult3